C#进行Visio二次开发之Web端启动绘图客户端并登录
有这样的需求,一个系统,包含Web端的后台和Winform的绘图客户端程序,用户需要在Web端能够启动绘图客户端,并且不需要重新登录(因为已经登录了Web端了)。
那么在IE的Web端,如何启动Winform做的绘图客户端程序呢?当然对于其他桌面应用程序也是一样的。
总体思路是:
1. 在asp.net页面中增加一个按钮或者菜单,连接是调用一个JavaScript函数实现启动程序
2. 客户端的用户的环境变量有该应用程序的目录路径信息
3. Winform的绘图客户端程序能够处理传递过来的命令行的参数,实现登录启动
详细操作介绍如下:
1、asp.net页面中Javascript的代码如下:
Code
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
>
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);
}
.
}
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
;
}
}
}
然后在程序的入口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);
}
}
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);
}
}
}
}
至此,当客户端安装了绘图客户端后,Path的路径将加入安装的路径,在Web端通过javascript调用程序启动即能进行响应,并通过CommandLine辅助类解析参数后进行登录。
但要主要的是,Javascript能够调用本地的程序,是需要在IE中设置启用Javascript权限许可才可以。
标签: none