Groups | Blog | Home
all groups > dotnet interop > february 2006 >

dotnet interop : DllImport for DeleteProfile results in the parmeter is incorrect


Chris Martinez
2/21/2006 10:35:43 AM
Anyone that has an idea of how to invoke the DeleteProfile function
from UserEnv.dll through P/Invoke is greatly appreciated. I cannot see
to find any example anywhere on the web of how to import this function.

Based on the original C prototype it seems like it should be very easy
to import, but I continuously get "The parameter is incorrect." (error
87), when the function is invoked.

The prototype in UserEnv.h is:

BOOL DeleteProfileA(
LPCSTR lpSidString,
LPCSTR lpProfilePath,
LPCSTR lpComputerName );

The import declaration I used is as follows:

[DllImport( "userenv.dll", CharSet = CharSet.Ansi,
EntryPoint = "DeleteProfileA", SetLastError = true )]
public static extern bool DeleteProfile(
string lpSidString,
string lpProfilePath,
string lpComputerName );

I have tried numerous variations, including the use of the Unicode
version, applying the MarshalAsAttribute with UnmanagedType.LPStr for
ANSI and UnmanagedType.LPWStr for Unicode, all of which have failed
with the same result.

The following is an example of invoking the function:

if ( !Win32.DeleteProfile( sid, null, Environment.MachineName ) )
Console.WriteLine( new Win32Exception( Marshal.GetLastWin32Error()
).Message );

According the MSDN documentation the lpProfilePath can be NULL and will
be looked up in the Registry. I've also tried specifying this
parameter with the correct path and it still fails. I'm 100% sure
that the SID translation is correct because both of the functions I
have to translate account name to SID and vice versa both work
correctly.

I'm currently running this on Windows XP SP2, using C# 1.1, but this
will also have to work on Win2K and Win2K3 (which I don't know why it
wouldn't).

Anyone that could shed some light on the subject would be greatly
appreciated.

Thanks,

Chris
Chris Martinez
2/24/2006 1:16:56 PM
[quoted text, click to view]

Unfortunately, I didn't get a reply from anyone, but I did finally
solve the problem. Hopefully this will be useful to anyone who needs
to write anything that deletes user profiles.

The original DLL import signature is correct and there is not anything
special that needs to be done in order to invoke the function. The
problem seems to be related to something that is still loaded in
memory.

For example, if I login as "User A", then log off and login as "User
B", and try to delete the user profile for "User A", the functions
fails. When inspecting the error code returned from "GetLastError",
the wonderfully ambiguous message (thanks MS!) reads "The parameter is
incorrect.".

When I thought I was going to have to abandon the use of
"DeleteProfile" and just delete the folders, etc. manually I began
receiving "Access Denied" errors, but not from ACLs (oddly I could
delete them from Windows Explorer). This lead me to believe resources
were still being locked.

Sure enough, running "DeleteProfile" from a cold or warm start worked
like a charm.

I'm not sure why resources would still be locked after a user acccount
has logged off, but it may have to do with some of the Terminal
Services technology borrowed in Windows XP to support the "Quick User
Swithing" and faster log ons features.

If any one ever comes up with a way to run this function after a
profile has been loaded, I'd interested to know how they did it. For
now, the best advice I can give is to run all of this type of code
during a cold or warm start.

Chris
AddThis Social Bookmark Button