How to share a folder on Windows 7 - c#

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
/

Related

Windows service. Edit the StartName

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

WMI access to UNC paths

I'm developing a server C# application which executes a .exe file through a local domain network on different client computers.
I've chosen to do it via WMI and works fine when the .exe path is local to the remote machine. Searching over other threads here and other forums I've noticed that WMI does not support UNC paths (here comes my problem).
When I call the method below to execute a .exe placed on the remote pc desktop, it just works fine:
var execResult = WmiExecuteRemoteProcess("XPSP3", #"C:\Documents and Settings\user1\Desktop\My_Setup.exe", #"domain\user", "mypass");
Now, when I try to use UNC paths, I get the exit code 2:
var execResult = WmiExecuteRemoteProcess("XPSP3", #"\\server\shared\My_Setup.exe", #"domain\user", "mypass");
The WmiExecuteRemoteProcess method looks like this:
public bool WmiExecuteRemoteProcess(string remoteComputerName, string arguments, string pUser, string pPassword)
{
try
{
ConnectionOptions connOptions = new ConnectionOptions();
connOptions.Username = pUser;
connOptions.Password = pPassword;
connOptions.Impersonation = ImpersonationLevel.Impersonate;
connOptions.EnablePrivileges = true;
ManagementScope manScope = new ManagementScope(string.Format(#"\\{0}\ROOT\CIMV2", remoteComputerName), connOptions);
manScope.Connect();
ObjectGetOptions objectGetOptions = new ObjectGetOptions();
ManagementPath managementPath = new ManagementPath("Win32_Process");
using (ManagementClass processClass = new ManagementClass(manScope, managementPath, objectGetOptions))
{
using (ManagementBaseObject inParams = processClass.GetMethodParameters("Create"))
{
inParams["CommandLine"] = arguments;
using (ManagementBaseObject outParams = processClass.InvokeMethod("Create", inParams, null))
{
return (uint)outParams["returnValue"] == 0;
}
}
}
}
catch (Exception ex)
{
Log.Error(ex.Message);
return false;
}
}
Given this situation I've decided kind of "cheat" it by parsing the arguments parameter as follows:
var args = "cmd.exe /c \"pushd \"\"\\\\server\\shared\"\" && My_Setup.exe && popd\"";
var execResult = WmiExecuteRemoteProcess("XPSP3",args,#"domain\user", "mypass");
What I try to do here is to use the cmd.exe with the commands pushd and popd to map the UNC path into a network drive-based path like "Z:\shared". This way both WMI and cmd.exe don't have to deal with the UNC path.
Result: again, if the .exe is local to the remote machine, it works very well, but when using a UNC path, only the cmd.exe process appears. Maybe it's internally throwing the exit code 2 again, but I'm not able to catch it, even redirecting the output of the cmd execution to a log file.
Perhaps someone experienced in this kind of mechanics can throw some light on this. I'd prefer not to develop an entire service only for this, or to use PsExec (maybe this one as a last resort).
Please let me know if I'm missing any info. Any comments will be much appreciated.
Regards.
Edit: I checked and it's not a matter of permissions to the shared folder or file.
In case anyone faces this or other related issue, this is how I solved it:
The issue is not that WMI cannot deal with UNC paths, but WMI operations are not allowed to access network resources due to security restrictions in Windows. It doesn't matter if you map the paths, it's just not authorized. In this particular case the workaround I ended up with, was to copy the setup.exe to a temporary folder in the remote machine, and finally execute it through WMI by accessing its local path just like I was doing before.
var execResult = WmiExecuteRemoteProcess("XPSP3", #"C:\temp_folder\My_Setup.exe", #"domain\user", "mypass");

Setting Custom Shell via WMI

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.

Getting strange error code when programmatically adding a machine to a domain using C#

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.

Access the Windows 7 Boot Configuration Data using C#

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.

Categories