wshnzxj

       这里来记录下今天在项目中遇到的一个小问题:

       我们自己打包的的一个windows服务想要访问远程共享盘下面的文件,本以为是一个很简单的功能,不就是远程访问吗,可事实并非如此,其中测试的时候,程序以exe可执行文件运行,OK这时候没毛病,一切正常,当我们打包服务的时候问题就出现了,错误日志显示:Access to the path \'\\xxxxxx\map\2020\0705\20B13748-48.txt\' is denied.  权限不够,借助度娘查阅了一些资料,大多说的都是修改目标服务器的权限,可是这个是客户重要服务器,我们是不能动的,这种方案就被pass掉了,我们经理提出了一种方案:

       给这个服务创建访问账号和密码,不要使用系统本身的账号的登录 

     

 

       设置过之后返现访问成功了,可是当我们重新卸载,安装服务的时候返现又不行了,又得重新设置过一遍,这种方式也不适合我们,当然你不需要重新安装服务这种方案是可行的。

       最后我们又找到一种方法,用代码的方式在运行的时候使用凭证登陆一次共享盘,其中的原理我也不是很清楚,在这里无法向大家做具体解释

namespace Read
{
    class Program
    {
        static Program()
        {
            NativeCredMan.WriteCred("共享盘ip", @"共享盘账号", "共享盘密码",CRED_TYPE.DOMAIN_PASSWORD, CRED_PERSIST.ENTERPRISE);
        }
        static void Main(string[] args)
        {
            while (true)
            {
                try
                {
                    var filePath = @"\\xxxxx\map\2020\0705\20B13748-48.txt";
                    StreamReader sr = new StreamReader(filePath, Encoding.Default);
                    StringBuilder sb = new StringBuilder("");
                    try
                    {
                        String line;
                        int ind = 0;
                        while ((line = sr.ReadLine()) != null)
                        {
                            ind++;
                            if (!string.IsNullOrEmpty(line) && line.StartsWith("."))
                            {
                                sb.Append(line.ToString());
                            }
                        }
                        Log.Write($"读取成功=>{sb.ToString()}");
                    }
                    catch (Exception e)
                    {
                        Log.WriteLog(e);
                    }
                }
                catch (Exception e)
                {
                    Log.WriteLog(e);
                    Console.WriteLine($"读取失败=>{e.Message}");
                }
                Thread.Sleep(5000);
            }
        }
    }
}
public class CertificateManager
    {
        /// <summary>         
        /// 凭据类型         
        /// </summary> 
        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,
        }

        internal class NativeCredMan
        {
            [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)]
            //删除凭据 
            static extern bool CredDelete(string target, CRED_TYPE type, int flags);

            //[DllImport("advapi32", SetLastError = true, CharSet = CharSet.Unicode)] 
            //static extern bool CredEnumerateold(string filter, int flag, out int count, out IntPtr pCredentials); 

            [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
            public static extern bool CredEnumerate(string filter, uint flag, out uint count, out IntPtr pCredentials);

            [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;
                internal static NativeCredential GetNativeCredential(Credential cred)
                {
                    var ncred = new NativeCredential
                    {
                        AttributeCount = 0,
                        Attributes = IntPtr.Zero,
                        Comment = IntPtr.Zero,
                        TargetAlias = IntPtr.Zero,
                        //Type = CRED_TYPE.DOMAIN_PASSWORD,                                         
                        Type = cred.Type,
                        Persist = (UInt32)cred.Persist,
                        CredentialBlobSize = (UInt32)cred.CredentialBlobSize,
                        TargetName = Marshal.StringToCoTaskMemUni(cred.TargetName),
                        CredentialBlob = Marshal.StringToCoTaskMemUni(cred.CredentialBlob),
                        UserName = Marshal.StringToCoTaskMemUni(cred.UserName)
                    };
                    return ncred;
                }
            }

            [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
            public 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;
            }
            /// <summary> 
            /// 向添加计算机的凭据管理其中添加凭据             
            /// </summary> 
            /// <param name="key">internet地址或者网络地址</param>             
            /// <param name="userName">用户名</param>             
            /// <param name="secret">密码</param>             
            /// <param name="type">密码类型</param>             
            /// <param name="credPersist"></param>             
            /// <returns></returns> 
            public static int WriteCred(string key, string userName, string secret, CRED_TYPE type, CRED_PERSIST credPersist)
            {
                var byteArray = Encoding.Unicode.GetBytes(secret);
                if (byteArray.Length > 512)
                    throw new ArgumentOutOfRangeException("The secret message has exceeded 512 bytes.");
                var cred = new Credential
                {
                    TargetName = key,
                    CredentialBlob = secret,
                    CredentialBlobSize = (UInt32)Encoding.Unicode.GetBytes(secret).Length,
                    AttributeCount = 0,
                    Attributes = IntPtr.Zero,
                    UserName = userName,
                    Comment = null,
                    TargetAlias = null,
                    Type = type,
                    Persist = credPersist
                };
                var ncred = NativeCredential.GetNativeCredential(cred);
                var written = CredWrite(ref ncred, 0);
                var lastError = Marshal.GetLastWin32Error();
                if (written)
                {
                    return 0;
                }

                var message = "";
                if (lastError == 1312)
                {
                    message = (string.Format("Failed to save " + key + " with error code {0}.", lastError)
                    + "  This error typically occurrs on home editions of Windows XP and Vista.  Verify the version of Windows is Pro/Business or higher.");
                }
                else
                {
                    message = string.Format("Failed to save " + key + " with error code {0}.", lastError);
                }
                return 1;
            }

            /// <summary>            
            /// 读取凭据            
            /// </summary> 
            /// <param name="targetName"></param>            
            /// <param name="credType"></param>            
            /// <param name="reservedFlag"></param> 
            /// <param name="intPtr"></param>            
            /// <returns></returns> 
            public static bool WReadCred(string targetName, CRED_TYPE credType, int reservedFlag, out IntPtr intPtr)
            {
                return CredRead(targetName, CRED_TYPE.DOMAIN_PASSWORD, reservedFlag, out intPtr);
            }

            /// <summary>             
            /// 删除凭据             
            /// </summary> 
            /// <param name="target"></param>             
            /// <param name="type"></param>             
            /// <param name="flags"></param>             
            /// <returns></returns> 
            public static bool DeleteCred(string target, CRED_TYPE type, int flags)
            {
                return CredDelete(target, type, flags);
            }
        }

    }
View Code

       希望这个几个方式能对大家有所帮助。

 

分类:

技术点:

相关文章:

  • 2022-12-23
  • 2021-12-31
  • 2021-08-28
  • 2021-10-04
  • 2021-09-01
  • 2022-12-23
  • 2021-04-06
  • 2022-12-23
猜你喜欢
  • 2021-07-08
  • 2022-01-01
  • 2021-11-29
  • 2022-12-23
  • 2021-11-06
  • 2022-12-23
  • 2022-12-23
相关资源
相似解决方案