C#进行Visio二次开发之Web端启动绘图客户端并登录
有这样的需求,一个系统,包含Web端的后台和Winform的绘图客户端程序,用户需要在Web端能够启动绘图客户端,并且不需要重新登录(因为已经登录了Web端了)。
那么在IE的Web端,如何启动Winform做的绘图客户端程序呢?当然对于其他桌面应用程序也是一样的。
总体思路是:
1. 在asp.net页面中增加一个按钮或者菜单,连接是调用一个JavaScript函数实现启动程序
2. 客户端的用户的环境变量有该应用程序的目录路径信息
3. Winform的绘图客户端程序能够处理传递过来的命令行的参数,实现登录启动
有这样的需求,一个系统,包含Web端的后台和Winform的绘图客户端程序,用户需要在Web端能够启动绘图客户端,并且不需要重新登录(因为已经登录了Web端了)。
那么在IE的Web端,如何启动Winform做的绘图客户端程序呢?当然对于其他桌面应用程序也是一样的。
总体思路是:
1. 在asp.net页面中增加一个按钮或者菜单,连接是调用一个JavaScript函数实现启动程序
2. 客户端的用户的环境变量有该应用程序的目录路径信息
3. Winform的绘图客户端程序能够处理传递过来的命令行的参数,实现登录启动
详细操作介绍如下:
1、asp.net页面中Javascript的代码如下:
2、为了使得Web端的Javascript能够调用EDNMS.UI.exe 的Winform程序,我们需要在安装Winform的时候,把安装路径加入到操作系统Path变量中,操作系统的Path变量的内容放置在注册表节点SYSTEM\\ControlSet001\\Control\\Session Manager\\Environment的Path中,下面是自定义安装操作的代码。
3、Winform的绘图客户端程序能够处理传递过来的命令行的参数,实现登录启动
首先介绍一个能够处理命令行参数的公共类,他可以接受参数并把它放置到字典中
然后在程序的入口Main函数中,增加对参数化的登录解析,如下所示
至此,当客户端安装了绘图客户端后,Path的路径将加入安装的路径,在Web端通过javascript调用程序启动即能进行响应,并通过CommandLine辅助类解析参数后进行登录。
但要主要的是,Javascript能够调用本地的程序,是需要在IE中设置启用Javascript权限许可才可以。
那么在IE的Web端,如何启动Winform做的绘图客户端程序呢?当然对于其他桌面应用程序也是一样的。
总体思路是:
1. 在asp.net页面中增加一个按钮或者菜单,连接是调用一个JavaScript函数实现启动程序
2. 客户端的用户的环境变量有该应用程序的目录路径信息
3. Winform的绘图客户端程序能够处理传递过来的命令行的参数,实现登录启动
详细操作介绍如下:
1、asp.net页面中Javascript的代码如下:
Code
javascript:Run('EDNMS.UI.exe -u admin -p 4f5a51484e3c639b7c0e606511fe062d5f55aa0509638b385ed179e6d7fe4e9b7342f04c7c74b625574d6aa009693f386cef7b49536c3a4bfb5372675e76bb134f746a84466b7da86703');
javascript:Run('EDNMS.UI.exe -u admin -p 4f5a51484e3c639b7c0e606511fe062d5f55aa0509638b385ed179e6d7fe4e9b7342f04c7c74b625574d6aa009693f386cef7b49536c3a4bfb5372675e76bb134f746a84466b7da86703');
Code
<script type="text/javascript" language="JavaScript">
function Run(command)
{
window.oldOnError = window.onerror;
window._command = command;
window.onerror = function (err){
if(err.indexOf('automation') != -1){
alert('命令已经被用户禁止!');
return true;
}
else return false;
};
try
{
var wsh = new ActiveXObject('WScript.Shell');
if(wsh)
wsh.Run(command);
window.onerror = window.oldOnError;
}
catch (e)
{
alert('找不到文件EDNMS-DE.EXE(或它的组件之一)。请确定路径和文件名是否正确,而且所需的库文件均可用。')
}
}
</script>
<script type="text/javascript" language="JavaScript">
function Run(command)
{
window.oldOnError = window.onerror;
window._command = command;
window.onerror = function (err){
if(err.indexOf('automation') != -1){
alert('命令已经被用户禁止!');
return true;
}
else return false;
};
try
{
var wsh = new ActiveXObject('WScript.Shell');
if(wsh)
wsh.Run(command);
window.onerror = window.oldOnError;
}
catch (e)
{
alert('找不到文件EDNMS-DE.EXE(或它的组件之一)。请确定路径和文件名是否正确,而且所需的库文件均可用。')
}
}
</script>
2、为了使得Web端的Javascript能够调用EDNMS.UI.exe 的Winform程序,我们需要在安装Winform的时候,把安装路径加入到操作系统Path变量中,操作系统的Path变量的内容放置在注册表节点SYSTEM\\ControlSet001\\Control\\Session Manager\\Environment的Path中,下面是自定义安装操作的代码。
Code
[RunInstaller(true)]
public class InstallAction : Installer
{
private string virtualRoot = string.Empty; // 安装虚拟路径
private string physicalRoot = string.Empty; // 安装物理路径
/// <summary>
/// 必需的设计器变量。
/// </summary>
private Container components = null;
public InstallAction()
{
// 该调用是设计器所必需的。
InitializeComponent();
}
public override void Install(IDictionary stateSaver)
{
base.Install(stateSaver);
try
{
.
//修改Path环境变量
UpdatePathEnvironment();
}
catch (Exception ex)
{
WriteLog(ex.Message + "\r\n " + ex.StackTrace);
}
}
/// <summary>
/// 加入安装文件的路径,方便Web端访问
/// </summary>
private void UpdatePathEnvironment()
{
//得到原来Path的变量值
string registerKey = "SYSTEM\\ControlSet001\\Control\\Session Manager\\Environment";
string key = "Path";
RegistryKey regKey = Registry.LocalMachine.OpenSubKey(registerKey);
string result = regKey.GetValue(key).ToString();
//添加新的值
if (result.IndexOf(physicalRoot) < 0)
{
result += string.Format(";{0}", physicalRoot);
}
regKey = Registry.LocalMachine.OpenSubKey(registerKey, RegistryKeyPermissionCheck.ReadWriteSubTree, RegistryRights.SetValue);
regKey.SetValue(key, result);
}
.
}
[RunInstaller(true)]
public class InstallAction : Installer
{
private string virtualRoot = string.Empty; // 安装虚拟路径
private string physicalRoot = string.Empty; // 安装物理路径
/// <summary>
/// 必需的设计器变量。
/// </summary>
private Container components = null;
public InstallAction()
{
// 该调用是设计器所必需的。
InitializeComponent();
}
public override void Install(IDictionary stateSaver)
{
base.Install(stateSaver);
try
{
.
//修改Path环境变量
UpdatePathEnvironment();
}
catch (Exception ex)
{
WriteLog(ex.Message + "\r\n " + ex.StackTrace);
}
}
/// <summary>
/// 加入安装文件的路径,方便Web端访问
/// </summary>
private void UpdatePathEnvironment()
{
//得到原来Path的变量值
string registerKey = "SYSTEM\\ControlSet001\\Control\\Session Manager\\Environment";
string key = "Path";
RegistryKey regKey = Registry.LocalMachine.OpenSubKey(registerKey);
string result = regKey.GetValue(key).ToString();
//添加新的值
if (result.IndexOf(physicalRoot) < 0)
{
result += string.Format(";{0}", physicalRoot);
}
regKey = Registry.LocalMachine.OpenSubKey(registerKey, RegistryKeyPermissionCheck.ReadWriteSubTree, RegistryRights.SetValue);
regKey.SetValue(key, result);
}
.
}
3、Winform的绘图客户端程序能够处理传递过来的命令行的参数,实现登录启动
首先介绍一个能够处理命令行参数的公共类,他可以接受参数并把它放置到字典中
Code
using System;
using System.Collections.Generic;
using System.Text;
namespace WHC.EDNMS.Commons
{
public class CommandArgs
{
Dictionary<string, string> mArgPairs = new Dictionary<string,string>();
public Dictionary<string, string> ArgPairs
{
get { return mArgPairs; }
}
public List<string> Params
{
get { return mParams; }
}
List<string> mParams = new List<string>();
}
public class CommandLine
{
/// <summary>
/// Parses the passed command line arguments and returns the result
/// in a CommandArgs object.
/// </summary>
/// The command line is assumed to be in the format:
///
/// CMD [param] [[-|--|\]<arg>[[=]<value>]] [param]
///
/// Basically, stand-alone parameters can appear anywhere on the command line.
/// Arguments are defined as key/value pairs. The argument key must begin
/// with a '-', '--', or '\'. Between the argument and the value must be at
/// least one space or a single '='. Extra spaces are ignored. Arguments MAY
/// be followed by a value or, if no value supplied, the string 'true' is used.
/// You must enclose argument values in quotes if they contain a space, otherwise
/// they will not parse correctly.
///
/// Example command lines are:
///
/// cmd first -o outfile.txt --compile second \errors=errors.txt third fourth --test = "the value" fifth
///
/// <param name="args">array of command line arguments</param>
/// <returns>CommandArgs object containing the parsed command line</returns>
public static CommandArgs Parse(string[] args)
{
char[] kEqual = new char[] { '=' };
char[] kArgStart = new char[] { '-', '\\' };
CommandArgs ca = new CommandArgs();
int ii = -1;
string token = NextToken( args, ref ii );
while ( token != null )
{
if (IsArg(token))
{
string arg = token.TrimStart(kArgStart).TrimEnd(kEqual);
string value = null;
if (arg.Contains("="))
{
string[] r = arg.Split(kEqual, 2);
if ( r.Length == 2 && r[1] != string.Empty)
{
arg = r[0];
value = r[1];
}
}
while ( value == null )
{
string next = NextToken(args, ref ii);
if (next != null)
{
if (IsArg(next))
{
ii--;
value = "true";
}
else if (next != "=")
{
value = next.TrimStart(kEqual);
}
}
}
ca.ArgPairs.Add(arg, value);
}
else if (token != string.Empty)
{
ca.Params.Add(token);
}
token = NextToken(args, ref ii);
}
return ca;
}
static bool IsArg(string arg)
{
return (arg.StartsWith("-") || arg.StartsWith("\\"));
}
static string NextToken(string[] args, ref int ii)
{
ii++;
while ( ii < args.Length )
{
string cur = args[ii].Trim();
if (cur != string.Empty)
{
return cur;
}
ii++;
}
return null;
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
namespace WHC.EDNMS.Commons
{
public class CommandArgs
{
Dictionary<string, string> mArgPairs = new Dictionary<string,string>();
public Dictionary<string, string> ArgPairs
{
get { return mArgPairs; }
}
public List<string> Params
{
get { return mParams; }
}
List<string> mParams = new List<string>();
}
public class CommandLine
{
/// <summary>
/// Parses the passed command line arguments and returns the result
/// in a CommandArgs object.
/// </summary>
/// The command line is assumed to be in the format:
///
/// CMD [param] [[-|--|\]<arg>[[=]<value>]] [param]
///
/// Basically, stand-alone parameters can appear anywhere on the command line.
/// Arguments are defined as key/value pairs. The argument key must begin
/// with a '-', '--', or '\'. Between the argument and the value must be at
/// least one space or a single '='. Extra spaces are ignored. Arguments MAY
/// be followed by a value or, if no value supplied, the string 'true' is used.
/// You must enclose argument values in quotes if they contain a space, otherwise
/// they will not parse correctly.
///
/// Example command lines are:
///
/// cmd first -o outfile.txt --compile second \errors=errors.txt third fourth --test = "the value" fifth
///
/// <param name="args">array of command line arguments</param>
/// <returns>CommandArgs object containing the parsed command line</returns>
public static CommandArgs Parse(string[] args)
{
char[] kEqual = new char[] { '=' };
char[] kArgStart = new char[] { '-', '\\' };
CommandArgs ca = new CommandArgs();
int ii = -1;
string token = NextToken( args, ref ii );
while ( token != null )
{
if (IsArg(token))
{
string arg = token.TrimStart(kArgStart).TrimEnd(kEqual);
string value = null;
if (arg.Contains("="))
{
string[] r = arg.Split(kEqual, 2);
if ( r.Length == 2 && r[1] != string.Empty)
{
arg = r[0];
value = r[1];
}
}
while ( value == null )
{
string next = NextToken(args, ref ii);
if (next != null)
{
if (IsArg(next))
{
ii--;
value = "true";
}
else if (next != "=")
{
value = next.TrimStart(kEqual);
}
}
}
ca.ArgPairs.Add(arg, value);
}
else if (token != string.Empty)
{
ca.Params.Add(token);
}
token = NextToken(args, ref ii);
}
return ca;
}
static bool IsArg(string arg)
{
return (arg.StartsWith("-") || arg.StartsWith("\\"));
}
static string NextToken(string[] args, ref int ii)
{
ii++;
while ( ii < args.Length )
{
string cur = args[ii].Trim();
if (cur != string.Empty)
{
return cur;
}
ii++;
}
return null;
}
}
}
然后在程序的入口Main函数中,增加对参数化的登录解析,如下所示
Code
[STAThread]
static void Main(string[] args)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
if (args.Length > 0)
{
//args = new string[] { "-u ", "admin", "-p", "4e0a40090737639a661f6e7109f1062c585dff410f668c3c5f836caf8ef54e9a695bfe48647bb62450457fe40b6c383c6dbd6e0002673a4ae14a74634679bb12487c7fc0406e7aac6611" };
LoginByArgs(args);
}
else
{
LoginNormal(args);
}
}
[STAThread]
static void Main(string[] args)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
if (args.Length > 0)
{
//args = new string[] { "-u ", "admin", "-p", "4e0a40090737639a661f6e7109f1062c585dff410f668c3c5f836caf8ef54e9a695bfe48647bb62450457fe40b6c383c6dbd6e0002673a4ae14a74634679bb12487c7fc0406e7aac6611" };
LoginByArgs(args);
}
else
{
LoginNormal(args);
}
}
Code
/// <summary>
/// 使用参数化登录
/// </summary>
/// <param name="args"></param>
private static void LoginByArgs(string[] args)
{
CommandArgs commandArgs = CommandLine.Parse(args);
if (commandArgs.ArgPairs.Count > 0)
{
#region 获取用户参数
string userName = string.Empty;
string identity = string.Empty;
foreach (KeyValuePair<string, string> pair in commandArgs.ArgPairs)
{
if ("U".Equals(pair.Key, StringComparison.OrdinalIgnoreCase))
{
userName = pair.Value;
}
if ("P".Equals(pair.Key, StringComparison.OrdinalIgnoreCase))
{
identity = pair.Value;
}
}
#endregion
if (!string.IsNullOrEmpty(userName) && !string.IsNullOrEmpty(identity))
{
bool bLogin = Portal.gc.LoginByIdentity(userName.Trim(), identity);
if (bLogin)
{
ShowMainDialog();
}
else
{
LoginNormal(args);
}
}
}
}
/// <summary>
/// 使用参数化登录
/// </summary>
/// <param name="args"></param>
private static void LoginByArgs(string[] args)
{
CommandArgs commandArgs = CommandLine.Parse(args);
if (commandArgs.ArgPairs.Count > 0)
{
#region 获取用户参数
string userName = string.Empty;
string identity = string.Empty;
foreach (KeyValuePair<string, string> pair in commandArgs.ArgPairs)
{
if ("U".Equals(pair.Key, StringComparison.OrdinalIgnoreCase))
{
userName = pair.Value;
}
if ("P".Equals(pair.Key, StringComparison.OrdinalIgnoreCase))
{
identity = pair.Value;
}
}
#endregion
if (!string.IsNullOrEmpty(userName) && !string.IsNullOrEmpty(identity))
{
bool bLogin = Portal.gc.LoginByIdentity(userName.Trim(), identity);
if (bLogin)
{
ShowMainDialog();
}
else
{
LoginNormal(args);
}
}
}
}
至此,当客户端安装了绘图客户端后,Path的路径将加入安装的路径,在Web端通过javascript调用程序启动即能进行响应,并通过CommandLine辅助类解析参数后进行登录。
但要主要的是,Javascript能够调用本地的程序,是需要在IE中设置启用Javascript权限许可才可以。
专注于代码生成工具、.Net/.NetCore 框架架构及软件开发,以及各种Vue.js的前端技术应用。著有Winform开发框架/混合式开发框架、微信开发框架、Bootstrap开发框架、ABP开发框架、SqlSugar开发框架等框架产品。
转载请注明出处:撰写人:伍华聪 http://www.iqidi.com
转载请注明出处:撰写人:伍华聪 http://www.iqidi.com