none
Windows Freigabe erstellen per remot oder umc Pfad? RRS feed

  • Frage

  • Hallo, ich versuche gerade ein kleines Programm zu schreiben womit ich Freigaben von eiem Rechner auslesen und auf einem anderen wieder einspielen kann. Das auslesen funktioniert super aber beim einlesen kann ich immer nur einen Lokalen-Pfad angeben, ich würde aber gerne per umc Pfad und oder über remote Freigaben anlegen können.

    Das ist der Code den ich habe:

    void QshareFolder()
    
            {
    
                //String FolderPath = @"D:\TestFreigabe";
    
                //String ShareName = "TestFreigabe";
    
                //String Description = "Eine Test-Freigabe";
    
    
    
                DataTable dtFreigaben;
    
                try
    
                {
    
                    // Create a ManagementClass object
    
                    ManagementClass managementClass = new ManagementClass("Win32_Share");
    
    
    
                    dtFreigaben = (DataTable)dbgFreigaben.DataSource;
    
                    foreach (DataRow dtRow in dtFreigaben.Rows)
    
                    {
    
                        // Create ManagementBaseObjects for in and out parameters
    
                        ManagementBaseObject inParams = managementClass.GetMethodParameters("Create");
    
    
    
                        ManagementBaseObject outParams;
    
    
    
                        // Set the input parameters
    
                        inParams["Description"] = "";
    
                        inParams["Name"] = dtRow["Freigabe"];
    
                        inParams["Path"] = dtRow["LocalPath"];
    
                        inParams["Type"] = 0x0; // Disk Drive
    
    
    
                        //Another Type:
    
                        // DISK_DRIVE = 0x0
    
                        // PRINT_QUEUE = 0x1
    
                        // DEVICE = 0x2
    
                        // IPC = 0x3
    
                        // DISK_DRIVE_ADMIN = 0x80000000
    
                        // PRINT_QUEUE_ADMIN = 0x80000001
    
                        // DEVICE_ADMIN = 0x80000002
    
                        // IPC_ADMIN = 0x8000003
    
                        //inParams["MaximumAllowed"] = int maxConnectionsNum;
    
                        // Invoke the method on the ManagementClass object
    
    
    
                        outParams = managementClass.InvokeMethod("Create", inParams, null);
    
                        // Check to see if the method invocation was successful
    
    
    
                        if ((uint)(outParams.Properties["ReturnValue"].Value) != 0)
    
                        {
    
                            throw new Exception("Unable to share directory.");
    
                        }
    
                    }
    
                }
    
                catch (Exception ex)
    
                {
    
                    //MessageBox.Show(ex.Message, "error!");
    
                }
    
            }

    Kann mir jemand einen Tipp oder etwas in der Richtung geben ich komme einfach nicht mehr weiter.

    Für Hilfe bin ich sehr Dankbar und hoffe auf Hilfe.

    Gruß Olli

    Donnerstag, 23. August 2018 16:15

Antworten

  • Sind diese beiden Methoden nicht theoretisch das selbe von der Funktionalität her? 

     ManagementClass managementClass = new ManagementClass("Win32_Share");
    
                    ManagementScope Scope = new ManagementScope(@"\\.\root\cimv2");
                    Scope.Connect();
    und 
    string computer = "Computer_B";
                string domain = "DOMAIN";
                string username = "AdminUserName";
    ...
                // create Session using computer, SessionOptions
                CimSession Session = CimSession.Create(computer, SessionOptions);

    das kann ja schon per Definition nicht das gleiche sein. Mit dem ersten Code greifst Du auf den lokalen Rechner zu, auf dem das Skript läuft, mit dem zweiten auf einen anderen Rechner.

    Das ist auch der Grund, warum Du bei letzterem die Benutzerangaben brauchst. Der Prozess mit den Anmeldedaten des aktuelle angemeldeten Benutzers ausgeführt. Lokal hat der ausreichende Rechte, aber eben wohl nicht auf dem anderen PC bzw. kann hier ggfs. keine automatische Anmeldung per NTLM verwendet werden.

    Letztendlich kannst Du den Code für die Erstellung der Freigaben so beibehalten, wie Du ihn hast. Nur muss das die Win32_Share.Create Methode eben nicht lokal, sondern über die Remote WMI Verbindung auf Srv2 aufgerufen werden.

    Der Einfacheit halber würde ich das mit:

    ManagementScope scope = new ManagementScope("\\\\Srv2\\root\\cimv2", options);
    scope.Connect();

    machen, wie auch im Beispiel des MSDN Artikels zu sehen.

    Ein vollständiges Beispiel für den Aufruf von Win32_Share.Create inkl. Möglichkeit, zu einem Remoterechner zu verbinden, findest Du in der Doku zur Win32_Share Klasse.

    private static void makeShare(string servername, string filepath, string sharename)
    {
        try
        {
            // 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);
        }
        catch (SystemException e)
        {
            Console.WriteLine("Error attempting to create share {0}:", sharename);
            Console.WriteLine(e.Message);
        }
    }


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET (2001-2018)
    https://www.asp-solutions.de/ - IT Beratung, Softwareentwicklung, Remotesupport

    Freitag, 24. August 2018 06:23
    Moderator

Alle Antworten

  • Hallo Olli,

    willst Du jetzt auf dem Quellrechner die Freigaben auslesen, die dieser Rechner selbst für andere bereitstellt oder die Remotefreigaben auf diesem PC, die auf Netzwerkfreigaben eines Servers, ... verweisen?

    Eine normale Freigabe, die auf dem PC selbst angelegt wird, muss meines Wissens nach immer auf einen lokalen Ordner zeigen. (Zumindest bei Client Betriebssystemen). Daher weiß ich nicht so genau, was Du eigentlich machen willst.

    Beschreib doch mal ein konretes Beispiel mit Angabe aller PCs, die involviert sind.


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET (2001-2018)
    https://www.asp-solutions.de/ - IT Beratung, Softwareentwicklung, Remotesupport


    Donnerstag, 23. August 2018 16:30
    Moderator
  • Okay, ich hab mich vielleicht ein wenig unklar ausgedrückt, also ich mach mal ein Beispiel:

    Ich befinde mich auf einem Server (ich nenne Ihn mal Srv1).

    Srv1 hat eine remote Verbindung zu Server 2 (Srv2).

    Auf Srv1 lese ich die Freigaben aus und möchte sie unmittelbar danach auf Srv2 nachbilden.

    Mit dem Code den ich oben gepostet habe kann ich ja wie auch von dir schon erwähnt nur mit einem lokalen Pfad arbeiten.

    Donnerstag, 23. August 2018 16:36
  • Hi,

    das sind dann aber nicht die Win32_Shares. Das wären die Freigaben, die Srv1 selbst bereitstellt.

    Wenn Du von Srv1 aus die verwendeten Netzlaufwerke auslesen willst, geht das bspw. so (hab grad nur ein VBScript Beispiel hier, es sollte aber in etwa klar sein, was das Skript macht und die Übertragung auf .NET sollte kein größeres Problem sein):

    Dim WmiTarget
    Dim WmiService
    Dim Collection
    Dim Item
    
        WmiTarget = "."
    
    Set WmiService = GetObject( "winmgmts:\\" & WmiTarget & "\root\CIMV2" )
    Set Collection = WmiService.ExecQuery( "SELECT * FROM Win32_MappedLogicalDisk" )
    
        For Each Item in Collection
            Wscript.Echo "Drive letter: " & Item.DeviceID
            Wscript.Echo "Network Path: " & Item.ProviderName
        Next
    
    Set Collection = Nothing
    Set WmiService = Nothing

    Mit WMI selbst kannst Du meines Wissens nach kein Netzlaufwerk erstellen. Dafür kannst Du aber WScript.Network verwenden.

    Dim Network
    Dim RemoteShare
    
    Set Network = CreateObject( "WScript.Network" )
        RemoteShare = "\\server\share"
    
        Network.MapNetworkDrive "X:", RemoteShare, True, "User", "Password"
    
    Set Network = Nothing

    HTH


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET (2001-2018)
    https://www.asp-solutions.de/ - IT Beratung, Softwareentwicklung, Remotesupport


    Donnerstag, 23. August 2018 16:55
    Moderator
  • Falls ich dich falsch verstanden habe und Du willst schon die lokalen Freigaben auf Srv1 selbst auslesen und die dann remote auf Srv2 anlegen: Das geht so nicht. Für die Anlage musst Du dich mit WMI auf Srv2 verbinden und dann dort den lokalen Pfad auf Srv2 angeben.

    In meinem VBScript Beispiel müsstest Du dafür WmiTarget "." mit "Srv2" ersetzen.

    Für ein .NET Beispiel schau mal in diese MSDN Artikel (Berechtigungen für die Zugriffe musst Du natürlich haben):

      Connecting to WMI Remotely with C#

      Connecting to WMI on a Remote Computer


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET (2001-2018)
    https://www.asp-solutions.de/ - IT Beratung, Softwareentwicklung, Remotesupport



    Donnerstag, 23. August 2018 16:58
    Moderator
  • Das ist genau was ich möchte. Sofort die freigegebenen Order auslesen und wieder erstellen auf einem anderen Server.

    Ich hab mir alles durchgelesen aber mir wird eine Sache nicht ganz klar. Sind diese beiden Methoden nicht theoretisch das selbe von der Funktionalität her? 

     ManagementClass managementClass = new ManagementClass("Win32_Share");
    
                    ManagementScope Scope = new ManagementScope(@"\\.\root\cimv2");
                    Scope.Connect();

    und 

    string computer = "Computer_B";
                string domain = "DOMAIN";
                string username = "AdminUserName";
    
    
                string plaintextpassword;
    
                Console.WriteLine("Enter password:");
                plaintextpassword = Console.ReadLine();
    
                SecureString securepassword = new SecureString();
                foreach (char c in plaintextpassword)
                {
                    securepassword.AppendChar(c);
                }
    
                // create Credentials
                CimCredential Credentials = new CimCredential(PasswordAuthenticationMechanism.Default,
                                                              domain,
                                                              username,
                                                              securepassword);
    
                // create SessionOptions using Credentials
                WSManSessionOptions SessionOptions = new WSManSessionOptions();
                SessionOptions.AddDestinationCredentials(Credentials);
    
                // create Session using computer, SessionOptions
                CimSession Session = CimSession.Create(computer, SessionOptions);

    Oder versteh ich das falsch. Seltsam kommt mir vor das bei der ersten Methode keine Login Daten etc. verwendet werden müssen

    Donnerstag, 23. August 2018 18:47
  • Ich habe gerade einen Beitrag gefunden der ebenfalls sagt das das wohl die gleiche funktion erfüllt aber die cimSession wohl moderner ist. Aber ich versteh jetzt nicht wie ich die Freigabe erstelle.

    Mit 

    CimSession Session = CimSession.Create(computer, SessionOptions);

    habe ich zwar jetzt die Verbindung aber zu meinem Remote Computer aber soetwas kann ich ja damit nicht machen : 

    outParams = managementClass.InvokeMethod("Create", inParams, null);

    Also mein Problem ist jetzt gerade das ich nach dem erstellen der Session nicht weiß wie ich weiter vorgehen muss :|

    Donnerstag, 23. August 2018 20:45
  • heißt das "CimSession.Create" quasi sofort eine verbindung herstellt und diese quasi "öffnet" und ich dannach einfach schon in etwa so weiter arbeiten kann? :

    ManagementClass managementClass = new ManagementClass("Win32_Share");
                ManagementBaseObject inParams = managementClass.GetMethodParameters("Create");
    
                ManagementBaseObject outParams;
    
                // Set the input parameters
                inParams["Description"] = "";
                inParams["Name"] = "";
                inParams["Path"] = "";
                inParams["Type"] = 0x0; // Disk Drive
    
                outParams = managementClass.InvokeMethod("Create", inParams, null);
    
                        // Check to see if the method invocation was successful
                if ((uint)(outParams.Properties["ReturnValue"].Value) != 0)
                {
                    thro

    Oder ich laufe gerade total in eine gedankliche Sackgasse...

    weil in meinem oberen Code mach ich das ja auch quasi so: 

    ManagementScope Scope = new ManagementScope(@"\\.\root\cimv2");
                    Scope.Connect();
                    
    
                    dtFreigaben = (DataTable)dbgFreigaben.DataSource;
    
                    foreach (DataRow dtRow in dtFreigaben.Rows)
                    {
                        // Create ManagementBaseObjects for in and out parameters
                        ManagementBaseObject inParams = managementClass.GetMethodParameters("Create");
    
                        ManagementBaseObject outParams;

    Hier wird ja auch ein Scope.Connect gemacht und danach bin ich ja mit dem Rechner/Server "verbunden" oder? Funktioniert das in etwa so wie ich mir das gerade vorstelle ? 


    • Bearbeitet Olli_Olli Donnerstag, 23. August 2018 21:15
    Donnerstag, 23. August 2018 21:13
  • Sind diese beiden Methoden nicht theoretisch das selbe von der Funktionalität her? 

     ManagementClass managementClass = new ManagementClass("Win32_Share");
    
                    ManagementScope Scope = new ManagementScope(@"\\.\root\cimv2");
                    Scope.Connect();
    und 
    string computer = "Computer_B";
                string domain = "DOMAIN";
                string username = "AdminUserName";
    ...
                // create Session using computer, SessionOptions
                CimSession Session = CimSession.Create(computer, SessionOptions);

    das kann ja schon per Definition nicht das gleiche sein. Mit dem ersten Code greifst Du auf den lokalen Rechner zu, auf dem das Skript läuft, mit dem zweiten auf einen anderen Rechner.

    Das ist auch der Grund, warum Du bei letzterem die Benutzerangaben brauchst. Der Prozess mit den Anmeldedaten des aktuelle angemeldeten Benutzers ausgeführt. Lokal hat der ausreichende Rechte, aber eben wohl nicht auf dem anderen PC bzw. kann hier ggfs. keine automatische Anmeldung per NTLM verwendet werden.

    Letztendlich kannst Du den Code für die Erstellung der Freigaben so beibehalten, wie Du ihn hast. Nur muss das die Win32_Share.Create Methode eben nicht lokal, sondern über die Remote WMI Verbindung auf Srv2 aufgerufen werden.

    Der Einfacheit halber würde ich das mit:

    ManagementScope scope = new ManagementScope("\\\\Srv2\\root\\cimv2", options);
    scope.Connect();

    machen, wie auch im Beispiel des MSDN Artikels zu sehen.

    Ein vollständiges Beispiel für den Aufruf von Win32_Share.Create inkl. Möglichkeit, zu einem Remoterechner zu verbinden, findest Du in der Doku zur Win32_Share Klasse.

    private static void makeShare(string servername, string filepath, string sharename)
    {
        try
        {
            // 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);
        }
        catch (SystemException e)
        {
            Console.WriteLine("Error attempting to create share {0}:", sharename);
            Console.WriteLine(e.Message);
        }
    }


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET (2001-2018)
    https://www.asp-solutions.de/ - IT Beratung, Softwareentwicklung, Remotesupport

    Freitag, 24. August 2018 06:23
    Moderator