1

我有一个用于加密和解密的 dotnet 脚本。我必须在 installshield 中传递 setvalues 函数的参数。我怎样才能做到这一点?点网代码如下。我有程序集(.dll)文件。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using System.Security;
using System.Xml;
using System.Collections.Specialized;

namespace EncryptionDecryption
{
    public class EncrptionHelper
    {
        #region Member variables      
        static byte[] entropy = { 0, 8, 2, 3, 5 };
        #endregion

        #region Public Methods

        public static void SetValue(string configFilePathName, string appSettingKey, string appSettingValue)
        {
            appSettingValue = EncryptString(ToSecureString(appSettingValue));
            SetSetting(appSettingKey, appSettingValue, configFilePathName);
        }

        public static string GetValue(string configFilePathName, string appSettingKey)
        {
            string value = GetSetting(appSettingKey, configFilePathName);           
            value = ToInsecureString( DecryptString(value));
            return value;
        }

        #endregion

        #region Private Methods
        private static bool SetSetting(string Key, string Value, string configFilePath)
        {
            bool result = false;
            try
            {
               // System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(configFilePath);
              //  config.AppSettings.File = configFilePath;
               // config.AppSettings.Settings[Key].Value = Value;     
               // config.Save(ConfigurationSaveMode.Modified);

                XmlDocument xmlDoc = new XmlDocument();
                xmlDoc.Load(configFilePath);
                xmlDoc.SelectSingleNode("//appSettings/add[@key='" + Key +"']").Attributes["value"].Value = Value;
                xmlDoc.Save(configFilePath);

                ConfigurationManager.RefreshSection("appSettings");

                result = true;
            }
            finally
            { }
            return result;
        }

        private static string GetSetting(string Key, string configFilePath)
        {
            string result = null;
            try
            {
                XmlDocument appSettingsDoc = new XmlDocument();
                appSettingsDoc.Load(configFilePath);
                XmlNode node = appSettingsDoc.SelectSingleNode("//appSettings");
                XmlElement value = (XmlElement)node.SelectSingleNode(string.Format("//add[@key='" + Key + "']"));
                result = (value.GetAttribute("value").ToString());
            }
            finally
            { }
            return result;
        }

        private static SecureString ToSecureString(string input)
        {
            SecureString secure = new SecureString();
            foreach (char c in input)
            {
                secure.AppendChar(c);
            }
            secure.MakeReadOnly();
            return secure;
        }

        private static string ToInsecureString(SecureString input)
        {
            string returnValue = string.Empty;
            IntPtr ptr = System.Runtime.InteropServices.Marshal.SecureStringToBSTR(input);
            try
            {
                returnValue = System.Runtime.InteropServices.Marshal.PtrToStringBSTR(ptr);
            }
            finally
            {
                System.Runtime.InteropServices.Marshal.ZeroFreeBSTR(ptr);
            }
            return returnValue;
        }

        private static string EncryptString(System.Security.SecureString input)
        {
            byte[] encryptedData = System.Security.Cryptography.ProtectedData.Protect(
                System.Text.Encoding.Unicode.GetBytes(ToInsecureString(input)), entropy, System.Security.Cryptography.DataProtectionScope.CurrentUser);

            return Convert.ToBase64String(encryptedData);
        }

        private static SecureString DecryptString(string encryptedData)
        {
            try
            {
                byte[] decryptedData = System.Security.Cryptography.ProtectedData.Unprotect(
                    Convert.FromBase64String(encryptedData),
                    entropy,
                    System.Security.Cryptography.DataProtectionScope.CurrentUser);

                return ToSecureString(System.Text.Encoding.Unicode.GetString(decryptedData));
            }
            catch
            {
                return new SecureString();
            }
        }

        #endregion
    }
}







Update: Action start 14:31:36: Encryption.
MSI (c) (84:40) [14:31:36:525]: Invoking remote custom action. DLL: C:\Users\<username>\AppData\Local\Temp\MSIE259.tmp, Entrypoint: m1
InstallShield: Attempting to load through CLR 4 APIs...
InstallShield: Getting meta host...
InstallShield: Enumerating available runtimes...
InstallShield: Highest available runtime: v4.0.30319
InstallShield: Trying to use highest runtime...
InstallShield: Using highest version runtime...
InstallShield: Loading assembly Security.Encryption from resource 4097
InstallShield: Calling method with parameters [(System.String)C:\Program Files (x86)\<Installdir>\<configfilename>.config, (System.String)VWFPassword, (System.String)]
InstallShield: Exception: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.IO.DirectoryNotFoundException: Could not find a part of the path 'C:\Program Files (x86)\<Installdir>\<configfilename>.config'.
   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
   at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath)
   at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize)
   at System.Xml.XmlDownloadManager.GetStream(Uri uri, ICredentials credentials, IWebProxy proxy, RequestCachePolicy cachePolicy)
   at System.Xml.XmlUrlResolver.GetEntity(Uri absoluteUri, String role, Type ofObjectToReturn)
   at System.Xml.XmlTextReaderImpl.OpenUrlDelegate(Object xmlResolver)
   at System.Threading.CompressedStack.runTryCode(Object userData)
   at 

System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)
   at System.Threading.CompressedStack.Run(CompressedStack compressedStack, ContextCallback callback, Object state)
   at System.Xml.XmlTextReaderImpl.OpenUrl()
   at System.Xml.XmlTextReaderImpl.Read()
   at System.Xml.XmlLoader.Load(XmlDocument doc, XmlReader reader, Boolean preserveWhitespace)
   at System.Xml.XmlDocument.Load(XmlReader reader)
   at System.Xml.XmlDocument.Load(String filename)
   at Security.Encryption.EncrptionHelper.SetSetting(String appSettingKey, String appsettingValue, String configFilePathName)
   at Security.Encryption.EncrptionHelper.SetValue(String configFilePathName, String appSettingKey, String appSettingValue)
   --- End of inner exception stack trace ---
   at System.RuntimeMethodHandle._InvokeMethodFast(IRuntimeMethodInfo method, Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeType typeOwner)
   at System.RuntimeMethodHandle.InvokeMethodFast(IRuntimeMethodInfo method, Object target, Object[] arguments, Signature sig, MethodAttributes methodAttributes, RuntimeType typeOwner)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at InstallShield.ClrHelper.CustomActionHelper.CallMethod(EntryPointInfo info)
   at InstallShield.ClrHelper.CustomActionHelper.RunAction(UInt32 installHandle, Int32 entryNumber, Int64 instanceHandle)
InstallShield: Managed code threw an unhandled exception.

这是我在完成以下屏幕截图中提到的所有操作并进行一些研发后收到的错误。调用加密自定义操作时,提到“C:\Program Files (x86)\\.config”的目录存在,但它会引发异常。

4

2 回答 2

1

是的,可以通过以下步骤完成: 1- 在 c# 安装程序类中编写所需的功能(确保您使用的是安装程序类)

2- 编译并将您的 dll 添加到 installshield 中(建议为此 dll 创建一个单独的组件) 3- 选择组件视图 -> 选择上面的组件并转到 .Net 设置部分,将“.Net Installer 类”设置为 true。设置“.net 安装程序类参数”

参数作为键/值对传递,例如

/targetDirectory="[INSTALLDIR]\"

所有步骤都相同,只是添加了屏幕截图。

  • 使用安装程序类和您的加密/解密类创建一个 dll。
  • 将 dll 和配置文件添加到组件(如上所述),如果配置文件已经添加到其他组件,那么它就可以了。无需再次添加。
  • 我已经添加并检索了 INSTALLDIR 变量作为预定义的参数。如果您想从用户(来自某些自定义文本框)接收一些输入,那么您需要定义自己的变量来存储和传递值作为参数。

  • 使用安装程序类和其他任务所需的逻辑创建 dll安装程序类

  • 创建组件并添加文件具有安装程序类和依赖项的组件
  • 将 dll 标记为安装程序类并传递参数传递参数

这是安装程序类:

using System;
using System.Text;
using System.IO;
using System.Diagnostics;
using System.ComponentModel;
using System.Configuration.Install;
using System.Collections.Generic;


namespace EncryptionDecryption
{
    [RunInstaller(true)]
    public class InstallerClassDemo : Installer
    {
        private string installationDirectory=string.Empty;
        private string testString=string.Empty ;

        public override void Install(System.Collections.IDictionary stateSaver)
        {
            base.Install(stateSaver);

            try
            {
                //For testing purpose only.. work only in debug mode when pdb files are deployed as well.
                //Debugger.Break();

                installationDirectory = Context.Parameters["INSTALLDIR"];

                //I believe, the config file must be located in the installation directory if so, then use the following way to compute path

                string configFilePath = Path.Combine(installationDirectory, "myConfigFile.config");
                EncrptionHelper.SetValue(configFilePath, "testKey", "testValue");
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex.Message);
            }

        }

        protected override void OnCommitted(System.Collections.IDictionary savedState)
        {
            base.OnCommitted(savedState);
        }

        public override void Uninstall(System.Collections.IDictionary savedState)
        {
            base.Uninstall(savedState);
        }


    }
}
于 2013-09-03T14:24:45.013 回答
0

我认为 installshield 不能(或需要额外的工作)来读取您的程序集,但您可以运行简单的控制台应用程序,该应用程序从 installscript 使用您的程序集并从 installshield 传递参数。

创建简单的控制台应用程序

在支持文件中包含控制台应用程序

复制到安装文件夹或程序集位置,以便控制台应用程序可以访问您的程序集

使用 launchappandwait 从 installscript 启动

如果consoleapp.exe 不再使用,只需将其删除。

于 2013-09-03T14:14:29.013 回答