Avatar billede dingemann Novice
04. maj 2011 - 18:59 Der er 5 kommentarer og
1 løsning

impersonate i Windows Service

Hej folkens,

Situationen er lidt svær men grundet omstændighederne er jeg nødt til at benytte mig af impersonate til forskellige funktioner i en Windows Service jeg er ved at udvikle på mit arbejde.
Problemet er kort fortalt at det er pissebesværligt for mig at debugge, ikke mindst fordi det er en Windwos Service, men også fordi impersonating relaterer sig til bruger/domæne hvilket gør at jeg bliver nødt til at installere Windows Servicen på den server der skal køre programmet, hver gang der skal debugges.

I princippet er det 'kun' opret bibliotek, kopier mappe, og lign men jeg har ladet mig forføre at denne løsning http://weblogs.asp.net/ralfw/archive/2003/11/24/39479.aspx og jeg er vild med tanken om bare at kunne indsætte en Begin og en End-blok og så have impersonated kode i mellem. Og grunden til at jeg er blevet forført er at jeg har riiimelig mange funktioner der skal køres som impersonate.

Imidlertid kan jeg ikke få koden til at du - det hele braser sammen uden at give en exception. Og jeg kan se en kommentar længere nede i tråden om at det ikke virker i Windows Services

Mit spørgsmål er selvfølgelig: hvad skal modficeres i koden så den virker til Windows Services - jeg begår mig normalt ikke i unmanged code og er ret så grøn.

Jeg er ligeglad med om du skriver i C# eller VB.NET - jeg er VB'er men har intet imod at læse C# - så hit it!
Avatar billede crilledk Nybegynder
05. maj 2011 - 10:41 #1
Jeg har lavet noget lignende engang. Hvor man skal logge på som en anden bruger end den der er på systemet og hente filer via UNC path. 

Jeg fandt løsningen her (a bit down the list):
http://objectmix.com/csharp/213292-accessing-unc-file-share-credentials.html

Jeg har en Zip fil med den kode der virker for mig, hvis det er det du leder efter?

Jeg kan se på dit eksempel at det du gør der liger MEGET det som jeg fandt.

Men i sidste ende kan jeg ikke svare på om det kan lade sig gøre gennem en service.

Kan du ikke installerer den lokalt og så start servicen med en anden bruger?

Cheers!
Avatar billede dingemann Novice
05. maj 2011 - 11:28 #2
Hey,

Jeg har prøvet at bygge det op omkring en webform på min lokale dunk da det er rimelig meget lettere at debugge i. Og jeg kan se at jeg får samme fejl. Access Denied. I koden har jeg skrevet min lokale Windows-account ind med brugernavn og adgangskode.

I koden er det som nævnt en start og en slutblok hvor det imellem skal køres impersonated.
Og det er det kode der står imellem der udløser fejlen Access Denied. An unhandled blah bla bla...
Jeg forstår det ikke helt - det er som nævnt min egen bruger jeg prøver med og jeg burde dælme ha rettigheder til at oprette en txt-fil på C:\

Men hvis du har et smart stykke kode som du vil dele så smid det venligst denne vej :D
Avatar billede crilledk Nybegynder
05. maj 2011 - 12:59 #3
Tja her er coden på en helper jeg har stykket sammen...

Se om du kan bruge det...

==
namespace Library

    ///
    /// http://objectmix.com/csharp/213292-accessing-unc-file-share-credentials.html
    public class CredentialsHelper
    {
        [DllImport("advapi32.dll", SetLastError = true)]
        private static extern bool LogonUser(string lpszUsername, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);

        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        private unsafe static extern int FormatMessage(int dwFlags, ref IntPtr lpSource, int dwMessageId, int dwLanguageId, ref String lpBuffer, int nSize, IntPtr* arguments);

        [DllImport("kernel32.dll", CharSet = CharSet.Auto,
        SetLastError = true)]
        private static extern bool CloseHandle(IntPtr handle);

        [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public extern static bool DuplicateToken(IntPtr existingTokenHandle, int SECURITY_IMPERSONATION_LEVEL, ref IntPtr duplicateTokenHandle);


        // logon types
        const int LOGON32_LOGON_INTERACTIVE = 2;
        const int LOGON32_LOGON_NETWORK = 3;
        const int LOGON32_LOGON_NEW_CREDENTIALS = 9;

        // logon providers
        const int LOGON32_PROVIDER_DEFAULT = 0;
        const int LOGON32_PROVIDER_WINNT50 = 3;
        const int LOGON32_PROVIDER_WINNT40 = 2;
        const int LOGON32_PROVIDER_WINNT35 = 1;

       
        public  FileInfo[] GetFiles(string userName, string domain, string password, string uncPath)
        {
            FileInfo[] files = null;
            IntPtr token = IntPtr.Zero;
            IntPtr dupToken = IntPtr.Zero;

            bool isSuccess = LogonUser(userName, domain, password,LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_DEFAULT, ref token);
            if (!isSuccess)
            {
                RaiseLastError();
            }

            isSuccess = DuplicateToken(token, 2, ref dupToken);
            if (!isSuccess)
            {
                RaiseLastError();
            }

           

            /***/
            WindowsIdentity newIdentity = new WindowsIdentity(dupToken);
            using (newIdentity.Impersonate())
            {
                //DirectoryInfo dirInfo = new DirectoryInfo(@"\\server\share");
                DirectoryInfo dirInfo = new DirectoryInfo(uncPath);
                files = dirInfo.GetFiles();
               
                /* foreach (FileInfo inf in files)
                {
                    Console.WriteLine("=> {0}", inf.FullName );
                } */
            }
           
            isSuccess = CloseHandle(token);
            if (!isSuccess)
            {
                RaiseLastError();
            }

            return files;
        }
       
     
        // GetErrorMessage formats and returns an error message
        // corresponding to the input errorCode.
        public unsafe static string GetErrorMessage(int errorCode)
        {
            int FORMAT_MESSAGE_ALLOCATE_BUFFER =
            0x00000100;
            int FORMAT_MESSAGE_IGNORE_INSERTS =
            0x00000200;
            int FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000;

            int messageSize = 255;
            string lpMsgBuf = "";
            int dwFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER |
            FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS;

            IntPtr ptrlpSource = IntPtr.Zero;
            IntPtr ptrArguments = IntPtr.Zero;

            int retVal = FormatMessage(dwFlags, ref ptrlpSource, errorCode, 0, ref lpMsgBuf, messageSize, &ptrArguments);
            if (retVal == 0)
            {
                throw new ApplicationException(
                string.Format("Failed to format message for error code '{0}'.", errorCode));
            }

            return lpMsgBuf;
        }

        private static void RaiseLastError()
        {
            int errorCode = Marshal.GetLastWin32Error();
            string errorMessage = GetErrorMessage(
            errorCode);

            throw new ApplicationException(errorMessage
            );
        }
    }
}
==
Avatar billede dingemann Novice
13. maj 2011 - 08:02 #4
hey - smid et svar! For dævlon da!
Avatar billede crilledk Nybegynder
13. maj 2011 - 08:11 #5
Virker det? :-)
Avatar billede dingemann Novice
03. juni 2011 - 08:31 #6
det gik skam fint! samtidig blev jeg også lige kort nødt til at læse op på hvad forskellen var på at spawne en ny tråd vs starte en ny process.
Som jeg kan læse mig til kan man kun impersonate spawnede tråde mens nye processer er noget andet der kører ved siden af.

Det jeg i sidste ende manglede var at kunne starte en ny process men jeg brugte da impersonation en del steder i den færdige kode til fx at skrive filer på netværksdrev.
Så tak for ko'jen.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester