I'm trying to set a custom shell in Windows 8.1 IND with the additional lock down features that come with this version of Windows.
I can successfully create the required entries in the Lock Down Manager and turn the custom shell on and off no problem via c# and WMI.
Because we're planning on deploying to a great number of devices, I want to problematically apply the custom shell setup too.
I'm using the WMI Code Generator to aid me in accessing and set the correct values.
However, both the WMI Code Generator and my C# app both crash when attempting to run the code generated by the generator to do this.
Unhandled Exception: System.ArgumentOutOfRangeException: Specified argument was
out of the range of valid values.
Parameter name: path
at System.Management.ManagementObject.ManagementObjectCTOR(ManagementScope sc
ope, ManagementPath path, ObjectGetOptions options)
at WMISample.CallWMIMethod.Main()
Code Sample:
public static void Main()
{
try
{
ManagementObject classInstance =
new ManagementObject("root\\StandardCimv2\\embedded",
"WESL_UserSetting", null);
// Obtain in-parameters for the method
ManagementBaseObject inParams =
classInstance.GetMethodParameters("SetCustomShell");
// Add the input parameters.
inParams["DefaultAction"] = 3;
inParams["Shell"] = "C:\\Dash\\someapp.exe";
inParams["Sid"] = "S-1-5-21-2560287794-1129801719-3036876794-1001";
// Execute the method and obtain the return values.
ManagementBaseObject outParams =
classInstance.InvokeMethod("SetCustomShell", inParams, null);
// List outParams
Console.WriteLine("Out parameters:");
Console.WriteLine("ReturnValue: " + outParams["ReturnValue"]);
}
catch(ManagementException err)
{
MessageBox.Show("An error occurred while trying to execute the WMI method: " + err.Message);
}
}
There is no path mentioned in the documentation. Can anyone advise why the code isn't setting the custom shell?
An old question, but I solved this problem by turning on the shell launcher as specified here: MSDN. It's under the "Turn on Shell Launcher" section.
Related
I need to check and edit the windows service's StartName.
I have founded this solution throught the WMI API:
using (var service = new ManagementObject($"Win32_Service.Name = '{my_name}'"))
{
using (var inParams = service.GetMethodParameters("Change"))
{
inParams["StartName"] = value;
ManagementBaseObject outParams = service.InvokeMethod("Change", inParams, null);
outParams.Dispose();
}
}
When I invoke this code by a new console project application with the Visual Studio that had been lauched as administrator it works fine.
But when I invoke it by the windows service that had loged as LocalSystem i got an exception:
System.Management.ManagementException: Provider Load Failur. in
System.Management.ManagementException.ThrowWithExtendedInfo(ManagementStatus
errorCode) in System.Management.ManagementObject.InvokeMethod(String
methodName, ManagementBaseObject inParameters, InvokeMethodOptions
options) ...
What have I missed in this case?
What permissions/application state or whatever do I must to change to edit the service StartName by the windows service?
I think that the better approach would be change the name in te registry. You will probably have to start Visual Studio as Administrator. Link: https://stackoverflow.com/a/3887455/637840
The Change() method on WMI got a lot of overhead you donĀ“t need. You will probably make a mistake on some parameter and potentially your service register is going to be broken. Take a look at everything you need to set in order to just change the name by WMI: https://learn.microsoft.com/es-es/windows/desktop/TermServ/win32-terminalservice-change
Anyway, if you need to do it by all means using WMI. You can use ORMi. You have a tutorial on the repo that will show you how to do method working.
Also you can use this as reference: https://medium.com/#luque.nicolas/compare-ormi-and-traditional-net-wmi-implementation-f00db26d10a3
I have written an application that installs Windows Roles and Features using the Powershell API. It works just fine in Windows 2008 R2, but nothing happens in Windows 2012; the program just moves on as if everything happened just fine, but nothing is installed.
I've tried making the program .NET v4.5 (it was .NET v2.0), but that didn't help. I've been all over Google about this and I can't find a solution that works. In fact, most say to use the sort of implementation that works in Windows 2008 R2. Here is my code:
public bool runPowerShell(string command, string args)
{
mLogger myLogger = mLogger.instance; //How I log stuff in my application.
bool done = false; //default Return value.
const string path = #"C:\\XMPLogs\\Roles and Features"; //Where Powershell output will go.
//Make sure Powershell log directory is there.
if (!Directory.Exists(path))
Directory.CreateDirectory(path);
//Start a new Powershell instance.
PowerShell powershell = PowerShell.Create();
System.Collections.ObjectModel.Collection<PSObject> output = new System.Collections.ObjectModel.Collection<PSObject>();
StringBuilder strBuilder = new StringBuilder(); //Used to examine results (for testing)
powershell.AddScript(#"Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy Unrestricted");
powershell.AddScript(#"Import-Module ServerManager");
//powershell.Invoke();
powershell.AddScript(command + " " + args);
try
{
output = powershell.Invoke();
// Construct a StringBuilder to examine the output of Invoke()
foreach (PSObject obj in output)
strBuilder.AppendLine(obj.ToString());
// Show the StringBuilder to see results (always empty!)
MessageBox.Show(strBuilder.ToString());
done = true;
}
catch (Exception ex)
{
string test = ex.ToString();
MessageBox.Show(test);
myLogger.output("ERRO", "PowerShell command " + command
+ "failed to run with arguments \"" + args + "\". Message: " + ex.ToString());
done = false;
}
powershell.Dispose();
return done;
}
I would call the method like this:
runPowerShell("add-windowsfeature", "-name FS-FileServer -logpath \"c:\\XMPLogs\\Roles and Features\\File Services.log\"");
The "output" object never has any data in it nor does the log file. So, I have no idea what is going on. I do know if I take the two parameters in the method call and enter them into a Powershell prompt manually, the install runs flawlessly.
Can anyone see what I'm doing wrong with this implementation on Windows Server 2012?
Thank you.
It's hard to know what is the real problem here, without more information. Perhaps you're not running your application as an administrator and therefore aren't allowed to add windows features?
However, PowerShell differs between terminating errors (which would block the execution and throw an exception, which should make your code enter the catch statement) and non-terminating errors (which are just written to the error stream and will not enter your catch statement).
You can read more about this if you run Get-Help Write-Error, Get-Help about_Throw and Get-Help about_Try_Catch_Finally.
I'm guessing your powershell command results in a non-terminating error. To find out whether a non terminating error has occured or not, you could check the powershell.HadErrors property and to get the error messages you can read the powershell.Streams.Error property.
This should probably help you in finding out what errors are occuring and hopefully help you solve your problem.
I am using C# to create a folder and share it on the network:
if (!System.IO.Directory.Exists(FolderPath))
{
System.IO.Directory.CreateDirectory(FolderPath);
// Calling Win32_Share class to create a shared folder
ManagementClass managementClass = new ManagementClass("Win32_Share");
// Get the parameter for the Create Method for the folder
ManagementBaseObject inParams = managementClass.GetMethodParameters("Create");
ManagementBaseObject outParams;
// Assigning the values to the parameters
inParams["Description"] = Description;
inParams["Name"] = ShareName;
inParams["Path"] = FolderPath;
inParams["Type"] = 0x0;
// Finally Invoke the Create Method to do the process
outParams = managementClass.InvokeMethod("Create", inParams, null);
// Validation done here to check sharing is done or not
if ((uint)(outParams.Properties["ReturnValue"].Value) != 0)
{
//MessageBox.Show("Folder might be already in share or unable to share the directory");
}
}
It works on XP, but I am not able to share a folder from this code on Windows 7.
Can anyone tell me how I can share a folder in Windows 7 using C#?
Your application will need to be running with Administrative access in order to share a folder.
If you have a look at the following link, it talks about what appears to be the same situation as what you are dealing with. About half way down there is an accepted answer which walks through the additional actions required for it to work on a Windows 7 machine.
Link: http://social.msdn.microsoft.com/Forums/en-US/windowssdk/thread/de213b61-dc7e-4f33-acdb-893aa96837fa
Hope this helps
Replace the
\
in your path with
/
I am trying to add a Windows machine (server 2008 R2) to a domain programmatically using C#. I know I have the correct permissions to add the machine to the domain because I am able to add it manually through the windows UI. I also know that my ManagementScope is correct because when I create it I am able to query any WMI object that I want. I am trying to connect as follows:
ManagementClass computerSystem = new ManagementClass(scope, new ManagementPath("Win32_ComputerSystem"), new ObjectGetOptions());
ManagementObjectCollection computerSystemInstances = computerSystem.GetInstances();
ManagementObject baseObject = computerSystemInstances.ToList<ManagementObject>().First();
ManagementBaseObject inParams = baseObject.GetMethodParameters("JoinDomainOrWorkgroup");
inParams["Name"] = "my.domain.com";
inParams["Password"] = domainCredentials.FullUserName;
inParams["UserName"] = domainCredentials.Password;
inParams["FJoinOptions"] = 1;
var joinParams = baseObject.InvokeMethod("JoinDomainOrWorkgroup", inParams, null);
The method invoke does not throw any exceptions, but the error code value found at joinParams.Properties["ReturnValue"].Value is 1312. I can't find any documentation anywhere (even on Microsoft's MSDN page for the method) stating what this error code means. Does anyone know where to find what this error code is for?
In your code, you've transposed your username and password to the wrong variables. This may be the cause?
This might be a system error code, found http://msdn.microsoft.com/en-us/library/ms681385%28v=vs.85%29
ERROR_NO_SUCH_LOGON_SESSION
1312 (0x520)
A specified logon session does not exist. It may already have been terminated.
I need to be able to access the identifier GUID of the current running installation of Windows from the Boot Configuration Data Store using c#. It can be returned from the command line running:
bcdedit /enum {current} /v
The problem I have is that in c# if I try to directly run this command (even though the program is running as Administrator) I'm told that bcdedit does not exist. I'm using:
ProcessStartInfo procStartInfo = new ProcessStartInfo("bcdedit.exe", "/enum {current} /v");
The other thing that I have researched is using WMI but the only reference I have to doing so is http://msdn.microsoft.com/en-us/library/windows/desktop/aa362673(v=vs.85).aspx which isn't very helpful.
The best solution would be if I don't have to use bcdedit but instead could use native WMI classes. How would I find the current Windows Boot Loader identifier using C#?
There seem to be many problems accessing bcdedit.exe directly but I was able to figure out how to use WMI in C# to access the BcdStore:
ConnectionOptions connectionOptions = new ConnectionOptions();
connectionOptions.Impersonation = ImpersonationLevel.Impersonate;
connectionOptions.EnablePrivileges = true;
// The ManagementScope is used to access the WMI info as Administrator
ManagementScope managementScope = new ManagementScope(#"root\WMI", connectionOptions);
// {9dea862c-5cdd-4e70-acc1-f32b344d4795} is the GUID of the System BcdStore
ManagementObject privateLateBoundObject = new ManagementObject(managementScope, new ManagementPath("root\\WMI:BcdObject.Id=\"{9dea862c-5cdd-4e70-acc1-f32b344d4795}\",StoreFilePath=\"\""), null);
ManagementBaseObject inParams = null;
inParams = privateLateBoundObject.GetMethodParameters("GetElement");
// 0x24000001 is a BCD constant: BcdBootMgrObjectList_DisplayOrder
inParams["Type"] = ((UInt32)0x24000001);
ManagementBaseObject outParams = privateLateBoundObject.InvokeMethod("GetElement", inParams, null);
ManagementBaseObject mboOut = ((ManagementBaseObject)(outParams.Properties["Element"].Value));
string[] osIdList = (string[]) mboOut.GetPropertyValue("Ids");
// Each osGuid is the GUID of one Boot Manager in the BcdStore
foreach (string osGuid in osIdList)
{
ManagementObject currentManObj = new ManagementObject(managementScope, new ManagementPath("root\\WMI:BcdObject.Id=\"" + osGuid + "\",StoreFilePath=\"\""), null);
MessageBox.Show("" + currentManObj.GetPropertyValue("Id"));
}
This gets the GUID of every Windows Boot Manager in the BcdStore and shows them in a MessageBox. It should be noted that you must have the right ConnectionOptions and that this program must be run as Administrator.
Thanks to Ross Johnston for his project at: http://www.codeproject.com/script/Articles/ViewDownloads.aspx?aid=18233 to find the BCD constants and to Tran Dinh Hop for his project at: http://www.codeproject.com/script/Articles/ViewDownloads.aspx?aid=19208 which has all of the C# code to work with the BcdStore (except for the aforementioned constants).
Update:
Using:
ManagementObject privateLateBoundObject = new ManagementObject(managementScope, new ManagementPath("root\\WMI:BcdObject.Id=\"{fa926493-6f1c-4193-a414-58f0b2456d1e}\",StoreFilePath=\"\""), null);
will obtain the BcdObject for the current, running Windows Boot Manager. If you then call:
currentManObj.GetPropertyValue("Id")
you will get the GUID of the current, running Windows Boot Manager which is different from "{fa926493-6f1c-4193-a414-58f0b2456d1e}" which is a link to the current Boot Manager.
Thanks to The Microsoft Scripting Guys and their project at: http://technet.microsoft.com/en-us/magazine/2008.07.heyscriptingguy.aspx?pr=blog for having that GUID constant that links to the current Boot Manager.
Note that there is only a 64-bit bcdedit.exe in %systemroot%\system32. If your app is 32-bit, it will not be able to launch the 64-bit bcdedit because the WOW64 layer remaps the system32\ directory to syswow64. It's definitely best to use the WMI interface.