I've created an application to get the OEM key and then activate Windows with that key. I can get the key from
ManagementObjectSearcher s = new ManagementObjectSearcher("SELECT * FROM SoftwareLicensingService");
But how can I activate Windows with that key? I can do that with Powershell as below:
$service = get-wmiObject -query 'select * from SoftwareLicensingService'
if($key = $service.OA3xOriginalProductKey){
Write-Host 'Activating using product Key:' $service.OA3xOriginalProductKey
$service.InstallProductKey($key)
}else{
Write-Host 'Key not found. Please contact IT for more information'
}
pause
You can call methods of a WMI object by using InvokeMethod of the ManagementObject. Here you are interested to invoke the InstallProductKey method of SoftwareLicensingService.
For example:
var searcher = new ManagementObjectSearcher(
"SELECT * FROM SoftwareLicensingServissce");
var obj = searcher.Get().Cast<ManagementObject>().First();
var inParams = obj.GetMethodParameters("InstallProductKey");
inParams["ProductKey"] = obj["OA3xOriginalProductKey"];
var outParams = obj.InvokeMethod("InstallProductKey", inParams, null);
MessageBox.Show(((PropertyData)outParams["ReturnValue"])?.Value?.ToString());
To run the example, make sure you "Run as Administrator".
Related
I want to uninstall a list of softwares silently, which I received from Windows Registry.
This has to be integrated in a WPF Application.
I have tried Cim, WMI, ManagementObjectSearcher for uninstalling as below
Get-CimInstance -Class Win32_Product | Where {$_.Name -like \"{returnStr}\"} | Remove-CimInstance".Replace("{returnStr}", softwareName)
ManagementObjectSearcher mos = new ManagementObjectSearcher("SELECT * FROM Win32_Product WHERE Name = '" + ProgramName + "'");
foreach (ManagementObject mo in mos.Get())
{
if (mo["Name"].ToString() == ProgramName)
{
object hr = mo.InvokeMethod("Uninstall", null);
}
}
Both these methods were unable to find the Software from the name that we got from Registry.
In ManagementObjectSearcher mos.Get() it throws Call Cancelled error.
Also tried the UninstallString from Registry which is also not working and I am getting options box for MsiExec.
Powershell script to uninstall these softwares also might help.
I'm trying to rename a printer using WMI in C#. I can run queries to select printers, but when I try to invoke the RenamePrinter method, I get an Access Denied result. I've tried running this application as administrator and creating a manifest, but I can't seem to invoke this method unless I'm actually running under the administrator account.
var oSearcher = new ManagementObjectSearcher(oMs, oQuery);
ManagementObjectCollection oReturnCollection = oSearcher.Get();
foreach (ManagementObject oReturn in oReturnCollection)
{
var objectClass = new ManagementClass("Win32_Printer");
var inParams = objectClass.GetMethodParameters("RenamePrinter");
inParams["NewPrinterName"] = "..."; // something
ManagementBaseObject oResult = oReturn.InvokeMethod("RenamePrinter", inParams, null);
var result = oResult["returnValue"]; // 5 = Access Denied
Is there some way I can invoke RenamePrinter under a normal user's account -- even if it means running as administrator?
I've been trying to do this, and I've found that I can't do this with certain network printers, but with local printers it works.
What I did was launch PowerShell as local admin and run it from there:
public void RenamePrinter(string strCurrentName, string strNewPrinterName)
{
var newProcessInfo = new System.Diagnostics.ProcessStartInfo
{
FileName = #"C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe",
Verb = "runas",
CreateNoWindow = true,
Arguments = "-Command \"$printer = get-wmiobject win32_printer | where { $_.Name -eq '" + strCurrentName + "' }; $printer.RenamePrinter('" + strNewPrinterName + "')\""
};
System.Diagnostics.Process.Start(newProcessInfo);
}
I receive the same "Access Denied" error when I attempt this with network printers (maybe it's a driver thing? I don't know) but this works for local printers.
I want to open process pon remote machine, this remote machine is inside local network.
I try this command and in the remote machine nothing happen, this user that i connect with have administrators rights.
Both machines running Windows 7
static void Main(string[] args)
{
try
{
//Assign the name of the process you want to kill on the remote machine
string processName = "notepad.exe";
//Assign the user name and password of the account to ConnectionOptions object
//which have administrative privilege on the remote machine.
ConnectionOptions connectoptions = new ConnectionOptions();
connectoptions.Username = #"MyDomain\MyUser";
connectoptions.Password = "12345678";
//IP Address of the remote machine
string ipAddress = "192.168.0.100";
ManagementScope scope = new ManagementScope(#"\\" + ipAddress + #"\root\cimv2", connectoptions);
//Define the WMI query to be executed on the remote machine
SelectQuery query = new SelectQuery("select * from Win32_process where name = '" + processName + "'");
object[] methodArgs = { "notepad.exe", null, null, 0 };
using (ManagementObjectSearcher searcher = new
ManagementObjectSearcher(scope, query))
{
foreach (ManagementObject process in searcher.Get())
{
//process.InvokeMethod("Terminate", null);
process.InvokeMethod("Create", methodArgs);
}
}
Console.ReadLine();
}
catch (Exception ex)
{
//Log exception in exception log.
//Logger.WriteEntry(ex.StackTrace);
Console.WriteLine(ex.StackTrace);
}
}
you are not opening a process with that code but you are enumerating all the running process named "iexplore.exe" and close them.
I think an easier, better way is to use SysInternals PsExec or the Task Scheduler API
If you want to use WMI your code should look like this:
object theProcessToRun = { "YourFileHere" };
ManagementClass theClass = new ManagementClass(#"\\server\root\cimv2:Win32_Process");
theClass.InvokeMethod("Create", theProcessToRun);
----------In reply to your comment------------------
First of all you need to change your attitude and approach to coding and read the code that your are copy/pasting.
Then you should study a little more about programming languages.
No I will not write the code for you. I gave you an hint to point to the right direction. now it is your turn to develop it. Have fun!!
This is script that i did for my company before this using vbs script. can search the net to convert it to C# or etc. Fundamental of the steps and how to start a service using WMI. Have a nice coding and have fun.
sUser = "TESTDomain\T-CL-S"
sPass = "Temp1234"
Set ServiceSet = GetObject("winmgmts:").ExecQuery("Select * from Win32_Service where Name = 'netlogon'")
For Each Service In ServiceSet
Service.StopService
Service.Change "netlogon",Service.PathName, , ,"Automatic",false,sUser,sPass
Service.StartService
Next
Set Service = Nothing
Set ServiceSet = Nothing
I'm trying to shutdown PC remotely programmatically using c# via command prompt and I already done a few search and found out this kind of codes.
System.Diagnostics.Process.Start("shutdown", "/s");
And since it doesn't spicify any pc which to shutdown so I tried changing that codes to this codes which I think satisfy my goal. But it turns out that this doesn't work.
System.Diagnostics.Process.Start("shutdown", "/s /m \\192.168.1.21 /t 5 /c 'Shutdown in 5 seconds'");
NO Exception in C# it just don't shutdown.
I also try this but no luck.
System.Diagnostics.Process.Start("shutdown /s /m \\192.168.1.21 /t 5 /c 'Shutdown in 5 seconds'");
C# Exception "The system cannot find file specified".
EDIT:
I forgot to tell you that I alredy set up my remote computer and server the way that it will not fail to connect to each other such as turning off the firewall, configuring Local system policy and changing network and sharing center.
// Remote Shutdown
public bool RemoteShutdown(string userName, string password, string ip)
{
try
{
ConnectionOptions op = new ConnectionOptions();
op.Username = userName;
op.Password = password;
// Make a connection to a remote computer.
ManagementScope scope = new ManagementScope("\\\\" + ip + "\\root\\cimv2", op);
scope.Connect();
//Query system for Operating System information
ObjectQuery oq = new ObjectQuery("SELECT * FROM Win32_OperatingSystem");
ManagementObjectSearcher query = new ManagementObjectSearcher(scope, oq);
ManagementObjectCollection queryCollection = query.Get();
foreach (ManagementObject obj in queryCollection)
{
obj.InvokeMethod("ShutDown", null); //shutdown
}
return true;
}
catch (Exception)
{
return false;
}
}
// Remote Reboot
public bool RemoteReboot(string userName, string password, string ip)
{
try
{
ConnectionOptions op = new ConnectionOptions();
op.Username = userName;
op.Password = password;
// Make a connection to a remote computer.
ManagementScope scope = new ManagementScope("\\\\" + ip + "\\root\\cimv2", op);
scope.Connect();
//Query system for Operating System information
ObjectQuery oq = new ObjectQuery("SELECT * FROM Win32_OperatingSystem");
ManagementObjectSearcher query = new ManagementObjectSearcher(scope, oq);
ManagementObjectCollection queryCollection = query.Get();
foreach (ManagementObject obj in queryCollection)
{
obj.InvokeMethod("Reboot", null); //shutdown
}
return true;
}
catch (Exception)
{
return false;
}
}
in C#, \\ in string means \
so the parameter interpreted as
/s /m \192.168.1.21 /t 5 /c 'Shutdown in 5 seconds'
you should use \\\\ to represent \\
or add an # mark before the start quote mark like this
System.Diagnostics.Process.Start("shutdown", #"/s /m \\192.168.1.21 /t 5 /c 'Shutdown in 5 seconds'");
You can have a look at the SO post below. It talks about rebooting a remote machine.
WMI to reboot remote machine
If you look at the Win32Shutdown method
Shutdown => 1 (0x1) & Reboot => 2 (0x2)
So in the SO link above you will have to change
// Add the input parameters.
inParams["Flags"] = 2; //Reboot
to
// Add the input parameters.
inParams["Flags"] = 1; //Shutdown
This should work:
System.Diagnostics.Process.Start("shutdown", #"-m \\192.168.1.21 -s -f -t 0");
Flags should be syntaxed like -m , not /m.
Even better is to create a "silent" shutdown (without cmd-window to show):
var shutdown = new ProcessStartInfo("shutdown", #"-m \\192.168.1.8 -s -f -t 0");
shutdown.CreateNoWindow = true;
shutdown.UseShellExecute = false;
Process.Start(shutdown);
Tested in win7, .Net framework 4.03
This is the code I use for shutdown / reboot remote machines:
int waitSeconds = 0;
string remoteHostNameOrIp = "192.168.0.1";
ProcessStartInfo processInfo = new ProcessStartInfo();
processInfo.FileName = "shutdown.exe";
processInfo.Arguments = $#"-s -t { waitSeconds } -m \\{ remoteHostNameOrIp }";
processInfo.WindowStyle = ProcessWindowStyle.Hidden;
processInfo.CreateNoWindow = true;
var proc = Process.Start(processInfo);
// Works without WaitForExit();
// When using this you can check in "proc" if the shutdown was accepted by
// the remote machine
//
// proc.WaitForExit();
You must also enable the "Remote Registry" service on the target computer, AND you must have admin rights on the remote computer.
See here for details.
thanks for the createnowindow, i was already thinking to use it if everything works (but its unusefull if you want to see what is happening)
No comments without explaination about my dashes. as long as i know, you can choose between - or /
try it yourself :-) Start+R (run) you will see it works :)
i think its to much work to solve it.
So i figgerd out that a able to use a file "FILENAME.cmd"
with "shutdown -s -m \IP -t 40" in it
The delay for reminder to close or save stuff (not nessecary)
the -f doesn't work for me
but with the cmd file i can call it and let it run from my application.
So my problem is solved, i know its a little bit.... not perfect. but it works at least.
Thanx to all for quick reply's
I am developing a C# program to remotely uninstall an application. It works fine but the problem is that it does not list all of the installed products on a particular selected computer.
The code for listing the installed product using WMI is :
void ListAllProducts()
{
try
{
ConnectionOptions connection = new ConnectionOptions();
connection.Username = Connect.UserName;
connection.Password = Connect.Password;
connection.Authority = "ntlmdomain:MSHOME";
ManagementScope scope = new ManagementScope("\\\\"+ Connect.MachineName +"\\root\\CIMV2", connection);
scope.Connect();
ObjectQuery query = new ObjectQuery("SELECT * FROM Win32_Product");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query);
System.Threading.Thread.Sleep(5000);
foreach (ManagementObject queryObj in searcher.Get())
{
listBox4.Items.Add(queryObj["Name"].ToString());
listBox2.Items.Add (queryObj["Name"].ToString ());
listBox1.Items.Add(queryObj["IdentifyingNumber"].ToString());
listBox3.Items.Add(queryObj["Version"].ToString());
}
}
catch (ManagementException e)
{
MessageBox.Show("An error occurred while querying for WMI data: " + e.Message);
}
}
The code for uninstalling all product is :
void UninstallProduct()
{
try
{
ConnectionOptions connection = new ConnectionOptions();
connection.Username = Connect.UserName;
connection.Password = Connect.Password;
connection.Authority = "ntlmdomain:MSHOME";
ManagementScope scope = new ManagementScope("\\\\"+Connect.MachineName +"\\root\\CIMV2", connection);
scope.Connect();
ManagementObject classInstance = new ManagementObject(scope, new ManagementPath ("Win32_Product.IdentifyingNumber='"+listBox1.Text +"',Name='"+listBox2.Text+"',Version='"+ listBox3.Text+"'"),null);
// no method in-parameters to define
// Execute the method and obtain the return values.
ManagementBaseObject outParams =
classInstance.InvokeMethod("Uninstall", null, null);
// List outParams
MessageBox.Show ("Uninstallation Starts");
}
catch(ManagementException err)
{
MessageBox.Show("An error occurred while trying to execute the WMI method: " + err.Message);
}
}
Please help me out to list all the products installed on the selected machine and to uninstall it without the consent of the user of that selected machine.
I believe your question relates to knowing which applications are installed on a remote machine. Once you know that, you can use your code to uninstall them. With that being the case, here is a link to an article on how to list all of the applications (with their uninstall information) on a remote computer:
http://mdb-blog.blogspot.com/2010/12/c-check-if-programapplication-is.html
The WMI Win32_Product only represents products that are installed by Windows Installer. To get a list of all installed products, you need to enumerate the subkeys of the SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall registry key. To do this remotely, you can use the WMI registry class StdRegProv class. TechNet includes sample scripts that show how this can be done, and which you can adapt to your particular needs:
How do I list all the installed applications on a given machine?
List Installed Software