I wrote a program using C# and make exe file using advanced installer and it work good but i want to make this exe file work in one computer, because some clints
take exe and give this exe to another and i want to privint that and protect my works
run the code below on the machine that you want your .exe. file to work on (it will give you this machines MAC address).
2. Add this MAC address to the code below
3. Add the code below to your C# code to ensure that it only runs on the machine with the correct MAC address (unique)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.NetworkInformation;
using System.Text;
using System.Threading.Tasks;
namespace OneMachine
{
class Program
{
static void Main(string[] args)
{
string clientMAC = "XX-XX-XX-XX-XX-XX"; // put the correct value here when you know it
string thisComputerMAC = GetMACAddress2();
Console.WriteLine("MAC:" + thisComputerMAC); // remove this when necessary
if (clientMAC == thisComputerMAC)
{
Console.WriteLine("this is the right computer");
} else
{
Console.WriteLine("PROGRAM WONT RUN ON THIS COMPUTER");
}
}
public static string GetMACAddress2()
{
NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces();
String sMacAddress = string.Empty;
foreach (NetworkInterface adapter in nics)
{
if (sMacAddress == String.Empty)// only return MAC Address from first card
{
//IPInterfaceProperties properties = adapter.GetIPProperties(); Line is not required
sMacAddress = adapter.GetPhysicalAddress().ToString();
}
} return sMacAddress;
}
}
}
reference: C# Get Computer's MAC address "OFFLINE"
I think what you want would be some sort of licence key and an authorization method.
A quick google turned up this article which you may find useful.
http://www.codeproject.com/Articles/28678/Generating-Unique-Key-Finger-Print-for-a-Computer
u can create the security constrain for exe like
by Giving unique password
By Entering the serial Key i.e. Licence Key which will know to u only or create random serial key generator based on the system.
You can allow only one user run your program by using a hardware ID to identify the user using the application or you can use a licensing system.
Related
I'm trying to automate configuring remote hosts, we have hundreds of these devices, we normally do it through USB programming, but if I could get a script to connect to these devices and do it programmatically, it would free up time.
These devices run some type of linux os, i'm not sure exactly, but they do have SSH enabled and confirm server host keys when you first connect to them via utility like PuTTY.
For now, i'm just trying to initiate an SSH session with the device. I've done quite a bit of research, and have come up with this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Renci.SshNet;
using Renci.SshNet.Common;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
//Connection information
string user = "admin";
string pass = "********";
string host = "IP Address";
//Set up the SSH connection
using (var client = new SshClient(host, user, pass))
{
//Accept Host key
client.HostKeyReceived += delegate (object sender, HostKeyEventArgs e)
{
e.CanTrust = true;
};
//Start the connection
client.Connect();
var output = client.RunCommand("show device details");
client.Disconnect();
Console.WriteLine(output.ToString());
Console.ReadLine();
}
}
}
}
The problem is this doesn't seem to execute the command listed. The console window comes up, and I can access the same device by WebGUI and see the log file, it shows a connection being made, but when I break the execution and see the variable values the output variable shows null.
If I let the execution sit, with the console window open (just shows a blinking cursor in the upper left), the connection times out after 10 minutes and connection is lost, which I also see happen in the device log.
Why would does this not seem to execute the runcommand and store the results in the output variable?
When you execute the RunCommand() method on an object of type Renci.SshNet.SshClient, it does not return the result as a variable.
Instead, it returns an object of the Renci.SshNet.SshCommand type.
The issue is that, it looks like you can't fit this resultant SshCommand object into a var.
This Renci.SshNet.SshCommand, returned when you execute RunCommand(), will contain several properties and methods.
The properties are:
CommandText
CommandTimeout
ExitStatus
OutputStream
ExtendedOutputStream
Result
Error
They're all useful, but as everything else seems to be working, the only relevant one you want is "Result".
The "Result" property will contain a String, which will be the host stream result of the command you provided to RunCommand().
As you mention the device's logfile has logged a successful connection being made, it looks like the connection is successful. So you'd just have to make the proper tweak to grab the Result, as described above, and you should be good to go.
Addendum:
The following line in the original post's code:
var output = client.RunCommand("show device details");
Should be replaced with this code:
var output = client.RunCommand("show device details").Result;
This will assign the Result property (which is a String) to the output var, which will give the desired outcome.
I want to perform iisreset programmatically from C# code over a list of servers with account having privilege to do that.
It's easy to do that for local machine for example that's a sample code:
// using ...
using System.Diagnostics;
public class YourForm : Form
{
// ...
private void yourButton_Click(object sender, EventArgs e)
{
Process.Start(#"C:\WINDOWS\system32\iisreset.exe", "/noforce");
}
// ...
}
Also:
using System.ServiceProcess;
using (ServiceController controller = new ServiceController())
{
controller.MachineName = “My local or remote computer name”;
controller.ServiceName = “IIS Service Name”; // i.e “w3svc”
if (controller.Status != ServiceControllerStatus.Running)
{
// Start the service
controller.Start();
Log.Debug(“IIS has been started successfully, now checking again for webservice availability”);
}
else
{
// Stop the service
controller.Stop();
// Start the service
controller.Start();
Log.Debug(“IIS has been restarted successfully”);
}
}
but how to perform this for more than one server.
Your first code snippet should work perfectly taking in considerations that there is no need to provide the full path of iisreset command.
Actually, you don't need that full path while calling IISRESET from CMD or Run tool. So, it is the same call.
Regarding user privilege, there are 2 approaches
You can pass desired user as an argument to Process.Start
Process.Start("iisreset", "server1", "admin", "admin password", "domain");
You can just call Process.Start as you did in your code, then make sure to run your application with the suitable user
I tried below and it worked perfectly
static void Main(string[] args)
{
string[] servers = LoadServersFromFile();
foreach (string server in servers)
{
Process.Start("iisreset", server.Trim());
}
}
private static string[] LoadServersFromFile()
{
//just listed all servers comma separated in a text file, change this to any other approach fits for your case
TextReader reader = new StreamReader("Servers.txt");
return reader.ReadToEnd().Split(',');
}
You probably need an impersonator to execute the above code.
I think the username and password used in the impersonator should have admin rights for that server (which you do).
You probably also need to remotely access the machine and then execute your code.
The post here, here and here might be of help to you.
Will update this post if something more useful comes to my mind.
EDIT:
You can try out the following steps:
Create a windows service with code for restarting the IIS
Deploy this service on all the servers for which you need to reset the IIS
Keep this service turned off
Remotely access this service (code to access services remotely is given in one of the posts above)
Start and stop the service. This will execute the code for resetting the IIS. Code for this is given here
Hope this helps.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.PointOfService;
using System.Collections;
namespace ScalePOS
{
class ScalePOS
{
static void Main(string[] args)
{
// Create a new instance of PosExplorer and use it to
// collect device information.
PosExplorer explorer = new PosExplorer();
DeviceCollection devices = explorer.GetDevices();
// Search all connected devices for an Scale, print its service object name
foreach (DeviceInfo device in devices)
{
if (device == null)
{
Console.WriteLine("device is null");
}
Console.WriteLine(device.ServiceObjectName);
Console.WriteLine(device.Type);
Console.WriteLine(device.HardwareId);
Console.ReadLine();
// It is important that applications close all open
}
}
}
}
I am trying to interface with a USB Scale and PosExplorer seems to not pick it up. When I run this code I get a bunch of Microsoft MSR,Scanner,Keylock simulators, but my scale is not picked up. Does anyone here know why not?
You can check for installed Service Objects through Visual Studio by opening the Server Explorer (View menu, then Server Explorer).
Once in the Server Explorer (which is presented as a tree), expand the "Servers" node, then your computer name node, then you can check for your particular device in either the "LogicalDevice", "POSDevice" or "ServiceObject" nodes.
I'd start with the "ServiceObject" node first!
Figured out what the issue was, I needed an OPOS Driver or a service object associated with the scale. As the manufacturer did not provide one I needed to create my own.
I have a report that gets updated every week that needs pushed out to 30+ PC's and the number is rising each week. I am trying to figure out how to take an Access Database and push the files out from a location on our server to all of each of those PC's but what I can't wrap my head around is how to do it. I was going to use a copy command and then use the value of the PC ID in a string and enter it into the file paths. This is a little bit more advanced than I am used to working with. Here's what I have so far:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
// TODO: This line of code loads data into the 'database1DataSet1.PCID_List' table. You can move, or remove it, as needed.
this.pCID_ListTableAdapter.Fill(this.database1DataSet1.PCID_List);
}
private void button_Close_Click(object sender, EventArgs e)
{
this.Close();
}
static void button_Run_Click(object sender, EventArgs e)
{
string reportLocationCopy = #"Location TBD";
string repLoc = #"Location TBD";
if (File.Exists(repLoc))
{
// If file already exists in destination, delete it
if (File.Exists(reportLocationCopy))
File.Delete(reportLocationCopy);
File.Copy(repLoc, reportLocationCopy);
}
}
}
}
What I would do is this:
Open a database connection that selects your required information. Then use a sqldata adapter/datatable to draw the number of rows. Then I would write a foreach statement that uses these PCs and sends the updated file. So off the top of my head...
//select query here and your connectionstring
//then fill table as seen below
SqlDataAdapter sDA = new SqlDataAdapter(query, connectionString);
DataTable table = new DataTable();
sDA.Fill(table);
foreach (DataRow row in table.Rows)
{
string pc = (row["PCs"].ToString());
//send files
}
This would be an option:
As the numbers of client PC are growing every week, why don`t you try writing web-service. It will provide the ease and central management.
Now you have two case:
If you are working on intranet, locally host your WCF service on IIS.
If you have website then create web-service for that, then your internet based remote client can access your data.
You might need three things:
WCF service
IIS hosting
Client Application
Blue sky idea here, this may not be possible for security reasons. Can you push the database files to a Dropbox account, which the other machines also reference? This would provide quick synchronization of the machines as the database files are updated.
For what it's worth...
If this is in an Enterprise, your sysadmins will have tools that can push to each PC. I've done similar things to push application releases, and they can script whatever you need.
It might be worthwhile to post the question in a Sys Admin forum like serverfault or everythingsysadmin.
If your really dead set on managing the distribution, you can have your application call a Web Service or check a shared drive on startup for a newer version of the file and download it (either ftp or straight copy).
Let the client do the lookup to avoid issues like the PC not being available. It also allows the client to cancel the load if they are in a hurry. Nothings worse that having an update forced on you when you need something quickly!
Using C#, how can I determine which program is registered as the default email client? I don't need to launch the app, I just want to know what it is.
Use the Registry class to search the registry. This console app demonstrates the principle.
using System;
using Microsoft.Win32;
namespace RegistryTestApp
{
class Program
{
static void Main(string[] args)
{
object mailClient = Registry.GetValue(#"HKEY_LOCAL_MACHINE\SOFTWARE\Clients\Mail", "", "none");
Console.WriteLine(mailClient.ToString());
}
}
}
You can look in the registry on the following key:
HKEY_LOCAL_MACHINE\SOFTWARE\Clients\Mail
You can read this registry key from
HKEY_LOCAL_MACHINE\SOFTWARE\Clients\Mail
Default email client depends on the user. HKLM lists all registered email clients; the first one returned may not be the current user's default. Better to read HKEY_CURRENT_USER\Software\Clients\Mail.
Also this only gives you the name of the email application. If you want its executable file name, you have to go on with something like:
object mailCommand = Registry.GetValue(#"HKEY_LOCAL_MACHINE\SOFTWARE\Clients\Mail\" + mailClient.ToString() + #"\shell\open\command", "", "none");
and then remove anything extraneous from the command-line string that you don't need (quotes, parameters).
I think you should be able to find that info in the registry at HKLM\Software\Clients\Mail.
Look for the default string value.