【澳门威斯尼人平台登录】excel 运行时自动展开文件

1. 问题

try
{
fs = new StreamReader(new FileStream(path, FileMode.Open,
FileAccess.Read),
Encoding.GetEncoding(“gb2312”));//正常读取文件,如果被excel程序独占的话,此时会抛出异常
}
catch(Exception e)
{
//抛出异常后,那么就可以拷贝此文件到临时文件夹下生成的一个随机文件中,然后读取此临时文件即可
string tempFile = Path.GetTempPath() + Path.GetRandomFileName();
File.Copy(path, tempFile);
fs = new StreamReader(new FileStream(tempFile, FileMode.Open,
FileAccess.Read), Encoding.GetEncoding(“gb2312”));
}

我们在工作中会使用各种文件,为了分类管理,我们建立了好多文件夹,在打开相应文件的时候,需要逐一打开文件路径找到文件,然后打开,下面介绍一个一键就可以打开文件的好方法。想要一键打开,我们先需要一个文件的路径。在win7系统中,文件的路径已经不再用传统的方式来表示路径,那么如何获得文件的路径呢?下面介绍一个方法。

来源:IT部落窝  作者:IT部落窝

 

当在console中调用API
ShellExecuteEx打开”test.iqy”文件时,发现excel会hang住,console退出后excel才会响应,但直接双击”test.iqy”是没有问题的,有意思的是这个情况只有在xp发生,在win7上没有这个问题。

1、打开文件夹,找到文件,我们看到的文件路径是这样的,并非用反斜杠字符来表示的。

内容提要:本文介绍excel启动时自动打开文件的两种方法。

澳门威斯尼人平台登录 1

 

澳门威斯尼人平台登录 2

我们每天使用EXCEL软件,总有一两个常用文件,其实我们可以进行相关设置,让excel启动时,自动为我们打开需要的文档,而不必我们去手动操作。

此问题的出现是因为意外情况导致Excel临时文件没有删掉,把C:\Program Files\Microsoft Office\Office12\XLSTART里面的临时文件“~$book”给删除就好了。

2. 重现步骤

2、用鼠标左键点击需要设置的文件,按下shift,然后右键,选择复制为路径。注意一定要按下shift键。

第一种excel启动时自动打开文件的方法:

澳门威斯尼人平台登录 3

澳门威斯尼人平台登录 ,重现环境:XP sp3 / Office 2007(其他office版本应该也可以,没有测试)

澳门威斯尼人平台登录 4

第一,找到需要随EXCEL启动的XLS文件,右击后选择“创建快捷方式”,在当前文件夹下创建XLS文件的快捷方式。然后右击该快捷方式,选择“剪切”。

 

3、按照这个方法,我们可以获得一个路径列表,粘贴在excel里。当然你也可以快速选择,批量复制:先用鼠标左键点击第一个文件,然后按下shift点击最后一个,这样就全部选中文件,按住shift不放松,右键选择复制为路径,再粘贴在Excel里,这是批量复制的方法。

第二,打开C:Program Files\Microsoft
Office\Office11\XLStart文件夹(C代表系统中OFFICE软件安装的分区盘符,默认为C盘),将刚才创建的XLS文件快捷方式“粘贴”到XLStart文件夹下。

1> 解压iqy_test.zip

澳门威斯尼人平台登录 5

我们再打开运行EXCEL软件,刚才创建快捷方式的XLS文件也随excel启动自动打开了。

2> 运行http_server.py(需先安装python)

4\如果想批量获得文件夹中的文件,还有一个函数可以实现,就是Excel宏表函数FILES,这个函数只能在定义名称当中使用。关于这个函数的用法,可以在百度找到,再此不再赘述。我写了一个数组公式,可以直接提取文件名,并屏蔽错误值。具体看演示。

技巧提示:(1)如果你要同时打开多个XLS文件,只需将欲打开的XLS文件的快捷方式都粘贴到XLStart文件夹下,就可以同时打开多个XLS文件。

3> 执行”shell_execute.exe test.iqy”

澳门威斯尼人平台登录 6

(2)如果把XLS文件直接剪切到这里,也可以达到文件自动随EXCEL启动而打开的目的。但如果系统盘出现问题文件就不一定能找到了,所以我们把快捷方式剪切过来就不会出现这样的问题。

shell_execute.exe的主要code:

5、路径提取到工作表以后,我们用两个函数的嵌套,来实现一键打开文件,其中HYPERLINK函数用来制造链接,mid函数提取文件名,作为HYPERLINK函数的第二个参数。

第二种excel启动时自动打开文件的方法:

bool shell_execute_file(wstring file_path)
{
    SHELLEXECUTEINFOW shell_exec_info = { 0 };
    shell_exec_info.cbSize = sizeof(SHELLEXECUTEINFOW);
    shell_exec_info.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI;
    shell_exec_info.hwnd = NULL;
    shell_exec_info.lpVerb = NULL;
    shell_exec_info.lpFile = file_path.c_str();
    shell_exec_info.lpParameters = NULL;
    shell_exec_info.lpDirectory = NULL;
    shell_exec_info.nShow = SW_SHOW;
    shell_exec_info.hInstApp = NULL;
    bool ret = ShellExecuteExW(&shell_exec_info);
    printf("process handle is %p\n", shell_exec_info.hProcess);

    return ret;
}

澳门威斯尼人平台登录 7

第一,将需要随excel启动时自动打开的文件存放在一个文件夹。

 

按照这样的方法,我们可以方便快捷的管理电脑中的文档,只要打开一个Excel工作簿,就可以一键打开,从而提高工作效率。

第二,单击菜单“工具/选项”,填写“常规”选项卡中的“启动时打开此项中的所有文件”。

3. 原因分析

我们再次运行EXCEL,文件就随启动自动打开了。

3.1 excel hang在哪里?

有了以上的方法,QQ群中一位网友的问题就好解决了。

3.1.1 用windbg附加到excel上,输入如下命令查看主线程hang住的地方

网友问:在启动Excel时,发现总是自动打开多个文件并导致启动速度慢了很多。请问如何才能解决此问题?

澳门威斯尼人平台登录 8

回答:启动Excel,在菜单中依次选择“工具→选项”命令。在打开的“选项”对话框中单击“常规”标签。删除“启动时打开此目录中的所有文件”输入的内容。或者是删除XLStart文件夹下的xls文件。这样,当再次启动excel时就不会自动打开文件了。

可以看到Excel
hang在NtUserMessageCall()中,经过查询知,SendMessage()内部就是调用NtUserMessageCall()来发送消息的。

关联阅读:《Word启动时自动打开文件的方法》

查看参数知excel调用NtUserMessageCall()类似如下:

NtUserMessageCall(HWND_BROADCAST, WM_DDE_INITIATE)

说明excel给所有顶层窗口发送一个WM_DDE_INITIATE消息,但是有窗口没有response

由此可以怀疑是由于console进程在和excel用DDE消息通信时,console没有响应excel发送的DDE消息,导致excel
hang住

 

3.2 为了验证3.1.1的猜想,用API Monitor一下ShellExecuteEx

3.2.1
根据微软的文档可知,发送DDE消息除了WM_DDE_INITIATE和WM_DDE_ACK之外用的都是PostMessage

在API Monitor中搜索一下PostMessage的调用,果然搜到一条

澳门威斯尼人平台登录 9

call stack显示确实是ShellExecuteEx所调用

澳门威斯尼人平台登录 10

消息1000为WM_DDE_EXECUTE,Post窗口句柄为0x00310172。

注意到下一个API GetWindowThreadProcessId ( 0x00310172 , 0x0012fb70
),刚好是获取这个窗口的pid和tid,查看下参数窗口:

这个窗口所属的进程PID =
0xc54,正好是excel的进程,说明ShellExecuteEx确实发送了DDE消息给excel,而且可执发送的消息的thread就是主线程

澳门威斯尼人平台登录 11

根据DDE的消息参数,可知wParam就是发送消息的窗口,其句柄为2425190 =
0x250166,反向查询知这是ShellExecuteEx创建的”WorkerW”窗口

澳门威斯尼人平台登录 12

澳门威斯尼人平台登录 13

 

3.2.2 为了验证3.2.1的结论,在PostMessageW上下断点跟踪一下

澳门威斯尼人平台登录 14

查看一下buff的地址:

澳门威斯尼人平台登录 15

刚好就是打开test.iqy的命令,说明ShellExecuteEx就是先创建了excel的进程,然后发送test.iqy的文件命令给excel打开。

 

3.3 总结

1> ShellExecuteEx打开test.iqy的时先创建excel进程

2> 然后创建一个”WorkerW”的窗口用于DDE通信

3> Post WM_DDE_EXECUTE给excel,告知打开test.iqy的命令

4> ShellExecuteEx执行结束,但并不destroy “WorkerW”窗口

5>
excel收到WM_DDE_EXECUTE消息后会广播WM_DDE_INITIATE消息,”WorkerW”窗口所在的console进程由于没有定义消息处理函数,ShellExecuteEx定义的”WorkerW”窗口消息处理函数得不到CPU执行机会,导致不会response该消息,从而导致excel
hang住

类似,我们可以创建一个带窗口的程序,启动后将其挂起,这时,即使直接双击打开test.iqy也会hang住。

 

4. 为什么双击打开excel不会hang住

因为双击打开实际是用explorer.exe打开,而explorer.exe是有窗口的,能够正常的接收处理WM_DDE_INITIATE消息

 

5. 为什么win7上不会有这样的问题

5.1 在API Monitor中看下PostMessageW

澳门威斯尼人平台登录 16

注意到win7下PostMessageW是用的线程2调用的,搜一下线程创建API
CreateThread

澳门威斯尼人平台登录 17

可知是ShellExecuteEx内部创建的线程,所以win7上ShellExecuteEx创建了一个线程专门用来处理和excel的DDE消息通信,这样就能正常的接收处理excel发过来的WM_DDE_INITIATE消息了

发表评论

电子邮件地址不会被公开。 必填项已用*标注