I have created an app to standardize user creation for our AD domain. Now I would like to be able to create, share and set permissions on the folder. I know how to create a remote folder, but I am unclear on the best way to go about sharing and setting permissions in VB08.
Thanks in advance,
Christopher
Just so people know what I ended up going with, here is the final successful code to create a remote folder, set NTFS permissions on the folder to full control for the selected user and then create a share on the new folder with full permissions for everyone.
using System.IO;
using System.Management;
using System.Security.AccessControl;
public static void CreateFolder(String accountName, String homeFolder)
{
String folderName;
String localfolderpath;
String shareName;
try
{
folderName = "\\\\server\\c$\\Home\\" + homeFolder + "\\" + accountName;
Directory.CreateDirectory(folderName);
localfolderpath = "C:\\Home\\" + homeFolder + "\\" + accountName;
shareName = accountName + "$";
FolderACL(accountName, folderName);
makeShare(localfolderpath, shareName);
}
catch (Exception ex)
{
MessageBox.Show("Error: " + ex.ToString());
}
}
public static void FolderACL(String accountName, String folderPath)
{
FileSystemRights Rights;
//What rights are we setting?
Rights = FileSystemRights.FullControl;
bool modified;
InheritanceFlags none = new InheritanceFlags();
none = InheritanceFlags.None;
//set on dir itself
FileSystemAccessRule accessRule = new FileSystemAccessRule(accountName, Rights, none, PropagationFlags.NoPropagateInherit, AccessControlType.Allow);
DirectoryInfo dInfo = new DirectoryInfo(folderPath);
DirectorySecurity dSecurity = dInfo.GetAccessControl();
dSecurity.ModifyAccessRule(AccessControlModification.Set, accessRule, out modified);
//Always allow objects to inherit on a directory
InheritanceFlags iFlags = new InheritanceFlags();
iFlags = InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit;
//Add Access rule for the inheritance
FileSystemAccessRule accessRule2 = new FileSystemAccessRule(accountName, Rights, iFlags, PropagationFlags.InheritOnly, AccessControlType.Allow);
dSecurity.ModifyAccessRule(AccessControlModification.Add, accessRule2, out modified);
dInfo.SetAccessControl(dSecurity);
}
private static void makeShare(string filepath, string sharename)
{
try
{
String servername = "server";
// assemble the string so the scope represents the remote server
string scope = string.Format("\\\\{0}\\root\\cimv2", servername);
// connect to WMI on the remote server
ManagementScope ms = new ManagementScope(scope);
// create a new instance of the Win32_Share WMI object
ManagementClass cls = new ManagementClass("Win32_Share");
// set the scope of the new instance to that created above
cls.Scope = ms;
// assemble the arguments to be passed to the Create method
object[] methodargs = { filepath, sharename, "0" };
// invoke the Create method to create the share
object result = cls.InvokeMethod("Create", methodargs);
MessageBox.Show(result.ToString());
}
catch (SystemException e)
{
Console.WriteLine("Error attempting to create share {0}:", sharename);
Console.WriteLine(e.Message);
}
}
here is nice tutorial http://weblogs.asp.net/cumpsd/archive/2004/02/08/69403.aspx
and home path you can get from %HOMEPATH% env. variable
Related
I am trying to connect to a remote server and access a specific directory in that server for searching a file but for some reason it shows that the directory doesnt exist on the server even though it actually exists. I am guessing that my file path is wrong. Can anyone please suggest me if I made a syntax error?
filepath = #"\\172.17.20.11\E$\MessageLogs\" + logType + "\\" + country + "\\" + year + "\\" + month + "\\" + day + "\\";
private void GetFiles(string filePath)
{
try
{
tblFileContent = new DataTable();
getColumns(tblFileContent);
//C:\MessageLogs\ElmaCore\KENYA\2016\March\22
//filePath = #"C:\MessageLogs\"+filePath; //Pick a folder on your machine to store the uploaded files
if (!Directory.Exists(filePath))
{
fn.MessageLine(this.Page, "Log folder does not exist.", System.Drawing.Color.Red, "lblMessageLine");
dtDate.Focus();
return;
}
string searchReference = txtReference.Text.Trim();
//string filePath = System.Configuration.ConfigurationManager.AppSettings["InFolder"].ToString();
DirectoryInfo DirInfo = new DirectoryInfo(filePath);
FileInfo[] CsvFiles = DirInfo.GetFiles("*" + searchReference + "*.log").OrderByDescending(p => p.LastWriteTime).ToArray();
if (CsvFiles.Length > 0)
{
foreach (var file in CsvFiles)
{
string FileName = file.Name;
string sourceFile = System.IO.Path.Combine(filePath, FileName);
ProcessFile(FileName, sourceFile);
}
//LoadGrid();
}
else {
fn.MessageLine(this.Page, "Sorry, No files found for the specified reference.", System.Drawing.Color.Red, "lblMessageLine");
txtReference.Focus();
return;
}
}
catch (Exception ex)
{
fn.MessageLine(this.Page, "Sorry an Error Occured. Please try again", System.Drawing.Color.Red, "lblMessageLine");
ErrLogger.LogError("filelog-" + ex.Message); //oledbconn.Close();
return;
}
}
As you say your directory exists than it might the problem with permission.
Please make sure account under which code is been running have permission to that folder.
Also note that once you deploy in IIS, change identity of apppool to a domain user who has permission.
If you want to verify if its permission problem, than just do this.
Right click into that folder and give permission to everyone and test.
how to enable a user to access vpn in active directory using c# programming language.
string username = "Abc user";
string _path;
string _filterAttribute;
try
{
DirectoryEntry myLdapconnection=new DirectoryEntry("domain");
myLdapconnection.Path = "LDAP://OU=,OU=,DC=,DC=,DC=";
myLdapconnection.AuthenticationType = AuthenticationTypes.Secure;
object obj = myLdapconnection.NativeObject;
DirectorySearcher search = new DirectorySearcher(myLdapconnection);
search.Filter = "(cn=" + username + ")";
search.PropertiesToLoad.Add("cn");
SearchResult result = search.FindOne();
s="True";
if (null == result)
{
s= "false";
}
// Update the new path to the user in the directory.
_path = result.Path;
_filterAttribute = (string)result.Properties["cn"][0];
}
catch (Exception ex)
{
s="Error authenticating user. " + ex.Message;
}
from the above code what the function of following statement is?
object obj = myLdapconnection.NativeObject;
Is this the statement to enable vpn?
if I add user to group then will he can use vpn connection?
Since obj is not used in the above code; it has no function and has nothing to do with VPN.
The code seems like it is trying to verify that a user exists, BUT it is weird.
I am trying to use c# to delete a user profile on a remote server. I am running the program as myself. If I browse to \\server\c$\Users\ as myself I can delete the directory "User". It gives no error. If I use my program written in C# with the code below to attempt to delete the same directory I get back this exception.
Access to the path 'appsFolder.itemdata-ms' is denied.
Am I doing something wrong with my delete?
Directory.Delete("\\\\server\\c$\\Users\\User\\",true);
Deleting a user profile folder without cleaning the registry accoringly can lead to several undesired side-effects like temporary profile creation etc.
i recommend using DeleteProfile function which can be found in userenv.dll
my code is as follow:
internal class Program
{
[DllImport("userenv.dll", CharSet = CharSet.Unicode, ExactSpelling = false, SetLastError = true)]
public static extern bool DeleteProfile(string sidString, string profilePath, string omputerName);
private static void Main(string[] args)
{
try
{
var username = args[0];
var principalContext = new PrincipalContext(ContextType.Domain); // Domain => to support local user this should be changed probably, didn't test yet
var userPrincipal = UserPrincipal.FindByIdentity(principalContext, username);
if (userPrincipal != null)
{
Console.WriteLine("User found");
var userSid = userPrincipal.Sid;
Console.WriteLine("User {0} has SID: {1}", username, userSid);
Console.WriteLine("Will try to DeleteProfile next..");
DeleteProfile(userSid.ToString(), null, null);
Console.WriteLine("Done - bye!");
}
else
{
Console.WriteLine("ERROR! User: {0} not found!", username);
}
}
catch (Exception exception)
{
Console.WriteLine(exception);
}
}
}
consider, this code is just for demonstration purpose and should be stabilized for production..
cheers,
-Chris
btw, here more on MSDN
https://msdn.microsoft.com/en-us/library/windows/desktop/bb762273(v=vs.85).aspx
Hi I was trying to same thing and found Directory.Delete() cannot delete files if file is Hidden or a system file.
Using cmd instead to delete folder.
public static FileAttributes RemoveAttribute (FileAttributes att, FileAttributes attToRemove)
{
return att & ~attToRemove;
}
public void DeleteProfileFolder(string file)
{
Process process = new Process();
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.WindowStyle = ProvessWindowsStyle.Hiddenl
startInfo.FileName = "cmd";
startInfo.Arguments = "/C rd /S /Q \"" + file + "\"";
process.StartInfo = startInfo;
process.Start();
process.WaitForExit();
}
public void Deletes(DirectoryInfo baseDir)
{
if(! baseDir.Exists)
return;
var Dirs = Directory.EnumerateDirectories(baseDir.ToString(),"*.*",SearchOption.TopDirectoryOnly);
var files = Directory.EnumerateFiles(baseDir.ToString(),"*.*",SearchOption.TopDirectoryOnly);
foreach(var dir in Dirs)
{
DeleteProfileFolder(dir);
}
foreach(var file in files)
{
FileAttributes att = File.GetAttributes(f);
if((att & FileAttributes.Hidden) == FileAttribute.Hidden)
{
att = RemoveAttribute(att, FileAttributes.Hidden);
File.SetAttributes(file , att);
File.SetAttributes(File, FileAttributes.Normal)
}
File.Delete(file);
}
}
To call This
Deletes("c:\Users\"); // did this on local system.
I havn't tried on network location but I thing this will work.
Note: To completely delete userProfile we also need to delete registry.
private bool GrantAccess(string fullPath)
{
DirectoryInfo dInfo = new DirectoryInfo(fullPath);
DirectorySecurity dSecurity = dInfo.GetAccessControl();
dSecurity.AddAccessRule(new FileSystemAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null), FileSystemRights.FullControl, InheritanceFlags.ObjectInherit | InheritanceFlags.ContainerInherit, PropagationFlags.NoPropagateInherit, AccessControlType.Allow));
dInfo.SetAccessControl(dSecurity);
return true;
}
Am using this method for remove the denied permission but its not working, please if any help to fix this.
using System;
using System.IO;
using System.Security.AccessControl;
namespace FileSystemExample
{
class DirectoryExample
{
public static void Main()
{
try
{
string DirectoryName = "TestDirectory";
Console.WriteLine("Adding access control entry for " + DirectoryName);
// Add the access control entry to the directory.
AddDirectorySecurity(DirectoryName, #"MYDOMAIN\MyAccount", FileSystemRights.ReadData, AccessControlType.Allow);
Console.WriteLine("Removing access control entry from " + DirectoryName);
// Remove the access control entry from the directory.
RemoveDirectorySecurity(DirectoryName, #"MYDOMAIN\MyAccount", FileSystemRights.ReadData, AccessControlType.Allow);
Console.WriteLine("Done.");
}
catch (Exception e)
{
Console.WriteLine(e);
}
Console.ReadLine();
}
// Adds an ACL entry on the specified directory for the specified account.
public static void AddDirectorySecurity(string FileName, string Account, FileSystemRights Rights, AccessControlType ControlType)
{
// Create a new DirectoryInfo object.
DirectoryInfo dInfo = new DirectoryInfo(FileName);
// Get a DirectorySecurity object that represents the
// current security settings.
DirectorySecurity dSecurity = dInfo.GetAccessControl();
// Add the FileSystemAccessRule to the security settings.
dSecurity.AddAccessRule(new FileSystemAccessRule(Account,
Rights,
ControlType));
// Set the new access settings.
dInfo.SetAccessControl(dSecurity);
}
// Removes an ACL entry on the specified directory for the specified account.
public static void RemoveDirectorySecurity(string FileName, string Account, FileSystemRights Rights, AccessControlType ControlType)
{
// Create a new DirectoryInfo object.
DirectoryInfo dInfo = new DirectoryInfo(FileName);
// Get a DirectorySecurity object that represents the
// current security settings.
DirectorySecurity dSecurity = dInfo.GetAccessControl();
// Add the FileSystemAccessRule to the security settings.
dSecurity.RemoveAccessRule(new FileSystemAccessRule(Account,
Rights,
ControlType));
// Set the new access settings.
dInfo.SetAccessControl(dSecurity);
}
}
}
more information here:
https://msdn.microsoft.com/en-us/library/system.io.directory.setaccesscontrol(v=vs.110).aspx
make sure your application run in high privilege
So i have this powershell code:
try{
$ComputerWMIObject = Get-WmiObject Win32_ComputerSystem -ComputerName "$oldComputerName" -Authentication 6
if ( $ComputerWMIObject ){
$result = $ComputerWMIObject.Rename("$newComputerName", $ADUserPassword , $ADUserName )
switch($result.ReturnValue)
{
0 {
if ( $Restart.IsChecked ) {
Get-WmiObject Win32_OperatingSystem -ComputerName "$oldComputerName" | ForEach-Object {$restart = $_.Win32Shutdown(6)}
$ResultText.Text = "Computer $oldComputerName was renamed to $newComputerName and restarted"
} else {
$ResultText.Text = "Computer $oldComputerName was renamed to $newComputerName restart computer to finish"
}
}
5 { $ResultText.Text = "Computer was not renamed. Please check if you have admin permissions (ReturnCode 5)" }
default { $ResultText.Text = "ReturnCode $($result.ReturnValue)"}
}
}else{
$ResultText.Text = "Couldn't create WMI Object on $oldComputerName"
}
}catch{
$ResultText.Text = $_
}
I'm trying to convert this to C# and can't find a way to do this. I just don't understand how to create WMI object.
It would be very helpful if you can post and example on how to do this.
I've read this Remotely change computer name for a Windows Server 2008 machine using C#? topic. And it throws an exception may be its because of this line:
Authentication = AuthenticationLevel.PacketPrivacy
I'm using System.Net.Security namespace and as it's stated in comment PacketPrivacy exists only there.
Since I can't ask there because I have low rating I've asked again.
Would be grateful if any one can help me.
PS: I know this can be done using NETDOM but I would prefer using WMI object.
ADDED:
I'm trying to use this:
var remoteControlObject = new ManagementPath
{
ClassName = "Win32_ComputerSystem",
Server = oldName,
Path = oldName + "\\root\\cimv2:Win32_ComputerSystem.Name='" + oldName + "'",
NamespacePath = "\\\\" + oldName + "\\root\\cimv2"
};
var conn = new ConnectionOptions
{
Authentication = AuthenticationLevel.PacketPrivacy,
Username = accountWithPermissions.Domain + "\\" + accountWithPermissions.UserName,
Password = accountWithPermissions.Password
};
var remoteScope = new ManagementScope(remoteControlObject, conn);
var remoteSystem = new ManagementObject(remoteScope, remoteControlObject, null);
ManagementBaseObject newRemoteSystemName = remoteSystem.GetMethodParameters("Rename");
var methodOptions = new InvokeMethodOptions();
newRemoteSystemName.SetPropertyValue("Name", newName);
newRemoteSystemName.SetPropertyValue("UserName", accountWithPermissions.UserName);
newRemoteSystemName.SetPropertyValue("Password", accountWithPermissions.Password);
ManagementBaseObject outParams = remoteSystem.InvokeMethod("Rename", newRemoteSystemName, null);
And I get this error Server RPC is unavailable. (Exception HRESULT: 0x800706BA) here:
ManagementBaseObject newRemoteSystemName = remoteSystem.GetMethodParameters("Rename");
ADDED2:
Ok, I guess I found out what causes an error.
i've changed original conn User name from
Username = oldName + "\\" + accountWithPermissions.UserName,
to
Username = accountWithPermissions.Domain + "\\" + accountWithPermissions.UserName,
and error happens, if I use old code I get ACCESS_IS_DENIED and that's correct because that user doesn't have rights.
So what's wrong if I use Domain\User may be I should change NamespacePath in remoteControlObject to be able to work with domain user authentication?
I was unable to find a way resolve this issue and no one seems to have an answer.
So I've solved this by using NETDOM when Server RPC is unavailable. (Exception HRESULT: 0x800706BA) actually any error happens I will add access denied check so it won't try NETDOM when this happens;
var remoteControlObject = new ManagementPath
{
ClassName = "Win32_ComputerSystem",
Server = oldName,
Path = oldName + "\\root\\cimv2:Win32_ComputerSystem.Name='" + oldName + "'",
NamespacePath = "\\\\" + oldName + "\\root\\cimv2"
};
string domain = accountWithPermissions.Domain;
string user = accountWithPermissions.UserName;
var conn = new ConnectionOptions
{
Authentication = AuthenticationLevel.PacketPrivacy,
Username = domain + "\\" + accountWithPermissions.UserName,
Password = accountWithPermissions.Password
};
var remoteScope = new ManagementScope(remoteControlObject, conn);
var remoteSystem = new ManagementObject(remoteScope, remoteControlObject, null);
try
{
ManagementBaseObject newRemoteSystemName = remoteSystem.GetMethodParameters("Rename");
newRemoteSystemName.SetPropertyValue("Name", newName);
newRemoteSystemName.SetPropertyValue("UserName", accountWithPermissions.UserName);
newRemoteSystemName.SetPropertyValue("Password", accountWithPermissions.Password);
ManagementBaseObject outParams = remoteSystem.InvokeMethod("Rename", newRemoteSystemName, null);
}
catch (Exception e)
{
this.Res.Inlines.Add(string.Format("Ошибка:\n" + e.Message + "\n"));
this.Res.Inlines.Add(string.Format("Пробуем переименовать используя NETDOM\n"));
bool restart = false;
PowerNETDOM(oldName, newName, accountWithPermissions, restart);
}
Server RPC is unavailable. (Exception HRESULT: 0x800706BA) is happening not because my changes to the script. This error if fired only by few PC's as I found out it can happen in many cases more about this here: Get-WmiObject : The RPC server is unavailable. (Exception from HRESULT: 0x800706BA) . And changing settings on a remote PC makes me go and check the settings directly from that PC. In that case I can just rename PC not even trying to find out what this happening. That's why I do use NETDOM because for some reason it doesn't have problems renaming that PC remotely.
private static void PowerNETDOM(String oldName, String newName, NetworkCredential accountWithPermissions, bool restart)
{
using (PowerShell PowerShellInstance = PowerShell.Create())
{
PowerShellInstance.AddScript
(
"param($Restart,$oldComputerName,$newComputerName,$ADUserPassword,$ADUserName);" +
"function ConvertTo-Encoding ([string]$From, [string]$To){" +
" Begin{ $encFrom = [System.Text.Encoding]::GetEncoding($from);$encTo = [System.Text.Encoding]::GetEncoding($to); }" +
" Process{ $bytes = $encTo.GetBytes($_);$bytes = [System.Text.Encoding]::Convert($encFrom, $encTo, $bytes);$encTo.GetString($bytes)}" +
"}" +
"$tmp = NETDOM RENAMECOMPUTER $oldComputerName /NewName:$newComputerName /ud:$ADUserName /pd:$ADUserPassword /Force $res_text | ConvertTo-Encoding \"cp866\" \"windows-1251\";" +
"$tmp > C:\\Temp\\rename.txt;$tmp;"
);
PowerShellInstance.AddParameter("restart", restart);
PowerShellInstance.AddParameter("newComputerName", newName);
PowerShellInstance.AddParameter("oldComputerName", oldName.ToString());
PowerShellInstance.AddParameter("ADUserPassword", accountWithPermissions.Password);
PowerShellInstance.AddParameter("ADUserName", accountWithPermissions.Domain + "\\" + accountWithPermissions.UserName);
PowerShellInstance.Invoke();
}
}