Я хочу удалить учетные данные после удаления.
internal class CredentialManager
{
public class AutoPinner : IDisposable
{
GCHandle _pinnerArray;
public AutoPinner(byte[] bytePtr)
{
_pinnerArray = GCHandle.Alloc(bytePtr, GCHandleType.Pinned);
}
public static implicit operator IntPtr(AutoPinner ap)
{
return ap._pinnerArray.AddrOfPinnedObject();
}
public void Dispose()
{
_pinnerArray.Free();
}
}
[DllImport("Advapi32.dll", EntryPoint = "CredReadW", CharSet = CharSet.Unicode, SetLastError = true)]
static extern bool CredRead(string target, CRED_TYPE type, int reservedFlag, out IntPtr CredentialPtr);
[DllImport("Advapi32.dll", EntryPoint = "CredWriteW", CharSet = CharSet.Unicode, SetLastError = true)]
static extern bool CredWrite([In] ref NativeCredential userCredential, [In] UInt32 flags);
[DllImport("Advapi32.dll", EntryPoint = "CredFree", SetLastError = true)]
static extern bool CredFree([In] IntPtr cred);
[DllImport("Advapi32.dll", EntryPoint = "CredDeleteW", CharSet = CharSet.Unicode, SetLastError = true)]
static extern bool CredDelete(string target, CRED_TYPE type, int flag);
public enum CRED_TYPE : uint
{
GENERIC = 1,
DOMAIN_PASSWORD = 2,
DOMAIN_CERTIFICATE = 3,
DOMAIN_VISIBLE_PASSWORD = 4,
GENERIC_CERTIFICATE = 5,
DOMAIN_EXTENDED = 6,
MAXIMUM = 7, // Maximum supported cred type
MAXIMUM_EX = (MAXIMUM + 1000), // Allow new applications to run on old OSes
}
public enum CRED_PERSIST : uint
{
SESSION = 1,
LOCAL_MACHINE = 2,
ENTERPRISE = 3,
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
private struct NativeCredential
{
public UInt32 Flags;
public CRED_TYPE Type;
public IntPtr TargetName;
public IntPtr Comment;
public System.Runtime.InteropServices.ComTypes.FILETIME LastWritten;
public UInt32 CredentialBlobSize;
public IntPtr CredentialBlob;
public UInt32 Persist;
public UInt32 AttributeCount;
public IntPtr Attributes;
public IntPtr TargetAlias;
public IntPtr UserName;
/// <summary>
/// This method derives a NativeCredential instance from a given Credential instance.
/// </summary>
/// <param name="cred">The managed Credential counterpart containing data to be stored.</param>
/// <returns>A NativeCredential instance that is derived from the given Credential
/// instance.</returns>
internal static NativeCredential GetNativeCredential(Credential cred)
{
NativeCredential ncred = new NativeCredential();
ncred.AttributeCount = 0;
ncred.Attributes = IntPtr.Zero;
ncred.Comment = IntPtr.Zero;
ncred.TargetAlias = IntPtr.Zero;
ncred.Type = (CRED_TYPE)cred.Type;
ncred.Persist = (UInt32)cred.Persist;
ncred.CredentialBlobSize = (UInt32)cred.CredentialBlobSize;
ncred.TargetName = Marshal.StringToCoTaskMemUni(cred.TargetName);
ncred.CredentialBlob = Marshal.StringToCoTaskMemUni(cred.CredentialBlob);
ncred.UserName = Marshal.StringToCoTaskMemUni(cred.UserName);
return ncred;
}
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
private struct Credential
{
public UInt32 Flags;
public CRED_TYPE Type;
public string TargetName;
public string Comment;
public System.Runtime.InteropServices.ComTypes.FILETIME LastWritten;
public UInt32 CredentialBlobSize;
public string CredentialBlob;
public CRED_PERSIST Persist;
public UInt32 AttributeCount;
public IntPtr Attributes;
public string TargetAlias;
public string UserName;
}
#region Critical Handle Type definition
sealed class CriticalCredentialHandle : CriticalHandleZeroOrMinusOneIsInvalid
{
// Set the handle.
internal CriticalCredentialHandle(IntPtr preexistingHandle)
{
SetHandle(preexistingHandle);
}
internal Credential GetCredential()
{
if (!IsInvalid)
{
// Get the Credential from the mem location
NativeCredential ncred = (NativeCredential)Marshal.PtrToStructure(handle,
typeof(NativeCredential));
// Create a managed Credential type and fill it with data from the native counterpart.
Credential cred = new Credential();
cred.CredentialBlobSize = ncred.CredentialBlobSize;
cred.CredentialBlob = Marshal.PtrToStringUni(ncred.CredentialBlob,
(int)ncred.CredentialBlobSize / 2);
cred.UserName = Marshal.PtrToStringUni(ncred.UserName);
cred.TargetName = Marshal.PtrToStringUni(ncred.TargetName);
cred.TargetAlias = Marshal.PtrToStringUni(ncred.TargetAlias);
cred.Type = ncred.Type;
cred.Flags = ncred.Flags;
cred.Persist = (CRED_PERSIST)ncred.Persist;
return cred;
}
else
{
throw new InvalidOperationException("Invalid CriticalHandle!");
}
}
internal NativeCredential GetNativeCredential()
{
if (!IsInvalid)
{
return (NativeCredential)Marshal.PtrToStructure(handle, typeof(NativeCredential));
}
else
{
throw new InvalidOperationException("Invalid CriticalHandle!");
}
}
// Perform any specific actions to release the handle in the ReleaseHandle method.
// Often, you need to use Pinvoke to make a call into the Win32 API to release the
// handle. In this case, however, we can use the Marshal class to release the unmanaged memory.
override protected bool ReleaseHandle()
{
// If the handle was set, free it. Return success.
if (!IsInvalid)
{
// NOTE: We should also ZERO out the memory allocated to the handle, before free'ing it
// so there are no traces of the sensitive data left in memory.
CredFree(handle);
// Mark the handle as invalid for future users.
SetHandleAsInvalid();
return true;
}
// Return false.
return false;
}
}
#endregion
public static bool WriteByteCred(string appName, string user, byte[] password)
{
bool result = false;
using (AutoPinner ap = new AutoPinner(password))
{
NativeCredential ncred = new NativeCredential();
ncred.AttributeCount = 0;
ncred.Attributes = IntPtr.Zero;
ncred.Comment = IntPtr.Zero;
ncred.TargetAlias = IntPtr.Zero;
ncred.Type = (CRED_TYPE)CRED_TYPE.GENERIC;
ncred.Persist = (UInt32)CRED_PERSIST.LOCAL_MACHINE;
ncred.CredentialBlobSize = (UInt32)password.Length;
ncred.CredentialBlob = ap;
ncred.TargetName = Marshal.StringToCoTaskMemUni(appName);
ncred.UserName = Marshal.StringToCoTaskMemUni(user);
// Write the info into the CredMan storage.
bool written = CredWrite(ref ncred, 0);
int lastError = Marshal.GetLastWin32Error();
if (written)
{
result = true;
}
else
{
string message = string.Format("CredWrite failed with the error code {0}.", lastError);
}
}
return result;
}
public static bool WriteCred(string appName, string user, string pasword)
{
// Validations.
byte[] byteArray = Encoding.Unicode.GetBytes(pasword);
if (byteArray.Length > 512)
throw new ArgumentOutOfRangeException("The password has exceeded 512 bytes.");
// Go ahead with what we have are stuff it into the CredMan structures.
Credential cred = new Credential();
cred.TargetName = appName;
cred.UserName = user;
cred.CredentialBlob = pasword;
cred.CredentialBlobSize = (UInt32)Encoding.Unicode.GetBytes(pasword).Length;
cred.AttributeCount = 0;
cred.Attributes = IntPtr.Zero;
cred.Comment = null;
cred.TargetAlias = null;
cred.Type = CRED_TYPE.GENERIC;
cred.Persist = CRED_PERSIST.LOCAL_MACHINE;
NativeCredential ncred = NativeCredential.GetNativeCredential(cred);
// Write the info into the CredMan storage.
bool written = CredWrite(ref ncred, 0);
int lastError = Marshal.GetLastWin32Error();
if (written)
{
return true;
}
else
{
string message = string.Format("CredWrite failed with the error code {0}.", lastError);
//throw new Exception(message);
//Log message in error log
return false;
}
}
public static byte[] ReadByteCred(string appName)
{
// Validations.
IntPtr nCredPtr;
// Make the API call using the P/Invoke signature
bool read = CredRead(appName, CRED_TYPE.GENERIC, 0, out nCredPtr);
int lastError = Marshal.GetLastWin32Error();
byte[] result = null;
// If the API was successful then...
if (read)
{
using (CriticalCredentialHandle critCred = new CriticalCredentialHandle(nCredPtr))
{
NativeCredential nativeCred = critCred.GetNativeCredential();
int blobSize = (int)nativeCred.CredentialBlobSize;
result = new byte[blobSize];
Marshal.Copy(nativeCred.CredentialBlob, result, 0, blobSize);
}
}
else
{
//1168 is "element not found" -- ignore that one and return empty string:
if (lastError != 1168)
{
string message = string.Format("ReadCred failed with the error code {0}.", lastError);
//Log meaasage here
//return readPasswordText;
}
}
return result;
}
public static string ReadCred(string appName)
{
// Validations.
IntPtr nCredPtr;
string readPasswordText = null;
// Make the API call using the P/Invoke signature
bool read = CredRead(appName, CRED_TYPE.GENERIC, 0, out nCredPtr);
int lastError = Marshal.GetLastWin32Error();
// If the API was successful then...
if (read)
{
using (CriticalCredentialHandle critCred = new CriticalCredentialHandle(nCredPtr))
{
Credential cred = critCred.GetCredential();
readPasswordText = cred.CredentialBlob;
}
}
else
{
readPasswordText = string.Empty;
//1168 is "element not found" -- ignore that one and return empty string:
if (lastError != 1168)
{
string message = string.Format("ReadCred failed with the error code {0}.", lastError);
//Log meaasage here
//return readPasswordText;
}
}
return readPasswordText;
}
public static void DeleteCredential(string appName)
{
CredDelete(appName, CRED_TYPE.GENERIC, 0);
}
}
Я создал класс установщика.
private void SetupManager_AfterUninstall(object sender, InstallEventArgs e)
{
try
{
if (CredentialManager.ReadByteCred(@"locahost/Guest") == null)
{
MessageBox.Show("NULL");
}
else
{
MessageBox.Show("NOT NULL");
CredentialManager.DeleteCredential(@"locahost/Guest");
}
}
catch(Exception ex)
{
writeException(ex, ex.StackTrace);
}
}
Он не работает. учетные данные не удаляются в диспетчере учетных данных.
Однако, это работает в приложении c#.
Я пытаюсь запустить командный файл для удаления учетных данных в классе установщика, но это тоже не работает.
cmdkey /delete:"locahost/Guest"
Однако, если я извиняюсь за этот пакетный файл, он работает.
System.Security.Principal.WindowsIdentity.GetCurrent().Name
Результатом этого является NT AUTHORITY \ SYSTEM.
Я думаю, что это может быть связано с NT AUTHORITY \ SYSTEM, что учетные данные не удалены.
Универсальные c учетные данные добавляются из установленной программы в качестве учетной записи пользователя.
Установщик выполняется как системная учетная запись.
Установщик удаляет учетные данные в системная учетная запись, а не учетная запись пользователя.
Как удалить общие учетные данные c, добавленные в качестве учетной записи пользователя во время или после удаления?