Visual C++项目通过 VStudio 运行良好,但在资源管理器中出现在通知托盘中后消失
我刚刚修改了我的 C++/CLI 项目来更改它解析 config.ini 文本文件的方式。但它仍然像以前一样访问磁盘上的文件:
StreamReader ^sr = gcnew StreamReader(CONFFILE_NAME);
String ^rdfl = sr->ReadToEnd();
sr->Close();
现在它不能在 VS2008Express 环境之外运行。它是一个伪装成服务的 WinForm,应该保留在通知托盘中,但它只是在那里闪烁其默认图标,直到我将鼠标滚动到它上面,这肯定表明它已经异常终止。顺便说一句,默认图标应该立即更新,所以我会再次检查这一点。我刚刚尝试过清理和重建。
谢谢。
_编辑_
如果配置文件不存在或不兼容,它运行正常 - 出现一个窗口,我输入正确的配置,然后她就走了。但它会从 VS2008 内部的文件重新加载配置数据,并且以前也从外部重新加载配置数据(尽管编码中存在重大逻辑错误)。
下面是紧随上面发布的代码:
int fore = 0;
int aft;
while (statsRead < 4) {
fore = rdfl->IndexOf(':', aft)+1;
if (fore == -1) break;
aft = rdfl->IndexOf('\n', fore);
if (aft == -1) break;
if (statsRead == 0) str1 = rdfl->Substring(fore, aft-fore)->Trim();
else if (statsRead == 1) str2 = rdfl->Substring(fore, aft-fore)->Trim();
else {
String ^tmpIntStr = rdfl->Substring(fore, aft-fore)->Trim();
int tmp_int;
if (Int32::TryParse(tmpIntStr, tmp_int)) {
switch (statsRead) {
case 2: int1 = tmp_int; break;
case 3: int2 = tmp_int; break;
}
} else break;
}
++statsRead;
}
}
之后,除了触发窗口的第一个之外,所有剩余的统计信息都会被赋予在我的情况下有效的默认值。
_编辑_
我已经按照 Hans 的主张使用 try 和 catch 块以及 StreamReader 的 MSDN 文献更新了上面的内容,但仍然失败,堆栈跟踪(谢谢, Hans) 表示错误是我的 while
语句(不,谢谢,MS)
if (File::Exists(CONFFILE_NAME)) {
String ^rdfl;
try {
StreamReader ^sr = gcnew StreamReader(CONFFILE_NAME);
try{
rdfl = sr->ReadToEnd();
} finally {
if ( sr )
delete (IDisposable^)sr;
}
} catch (Exception ^ex) {
MessageBox::Show(ex->Message);
}
int fore = 0;
int aft;
while (statsRead < 4) {
fore = rdfl->IndexOf(':', aft)+1;
if (fore == -1) break;
aft = rdfl->IndexOf('\n', fore);
if (aft == -1) break;
if (statsRead == 0) str1 = rdfl->Substring(fore, aft-fore)->Trim();
else if (statsRead == 1) str2 = rdfl->Substring(fore, aft-fore)->Trim();
else {
String ^tmpIntStr = rdfl->Substring(fore, aft-fore)->Trim();
int tmp_int;
if (Int32::TryParse(tmpIntStr, tmp_int)) {
switch (statsRead) {
case 2: int1 = tmp_int; break;
case 3: int2 = tmp_int; break;
}
} else break;
}
++statsRead;
}
}
I just modified my C++/CLI project to change the way it was parsing its config.ini text file. But it still accesses the file on the disk just as before:
StreamReader ^sr = gcnew StreamReader(CONFFILE_NAME);
String ^rdfl = sr->ReadToEnd();
sr->Close();
Now it won't run outside of the VS2008Express environment. It is a WinForm pretending to be a service and should stay in the notification tray but instead it just flashes its default icon there until I roll my mouse over it, a sure sign it has already terminated abnormally. The default icon should immediately be updated btw so I will check upto that point again. I've just tried a clean and rebuild.
Thanks.
_EDIT_
It runs fine if the config file is not there or is incompatible - a window appears and I enter the correct config and off she goes. But it reloads config data from a file from within VS2008 and it used to from without (albeit with a major logical error in the coding).
Here's the code immediately following that posted above:
int fore = 0;
int aft;
while (statsRead < 4) {
fore = rdfl->IndexOf(':', aft)+1;
if (fore == -1) break;
aft = rdfl->IndexOf('\n', fore);
if (aft == -1) break;
if (statsRead == 0) str1 = rdfl->Substring(fore, aft-fore)->Trim();
else if (statsRead == 1) str2 = rdfl->Substring(fore, aft-fore)->Trim();
else {
String ^tmpIntStr = rdfl->Substring(fore, aft-fore)->Trim();
int tmp_int;
if (Int32::TryParse(tmpIntStr, tmp_int)) {
switch (statsRead) {
case 2: int1 = tmp_int; break;
case 3: int2 = tmp_int; break;
}
} else break;
}
++statsRead;
}
}
afterwards any remaining stats are given default values which work in my case, apart from the first which triggers the window.
_EDIT_
I've updated the above with try and catch blocks as advocated by Hans and also the MSDN literatur for StreamReader but still it fails, the stack trace (thanks, Hans) indicates the fault is my while
statement (no thanks, MS)
if (File::Exists(CONFFILE_NAME)) {
String ^rdfl;
try {
StreamReader ^sr = gcnew StreamReader(CONFFILE_NAME);
try{
rdfl = sr->ReadToEnd();
} finally {
if ( sr )
delete (IDisposable^)sr;
}
} catch (Exception ^ex) {
MessageBox::Show(ex->Message);
}
int fore = 0;
int aft;
while (statsRead < 4) {
fore = rdfl->IndexOf(':', aft)+1;
if (fore == -1) break;
aft = rdfl->IndexOf('\n', fore);
if (aft == -1) break;
if (statsRead == 0) str1 = rdfl->Substring(fore, aft-fore)->Trim();
else if (statsRead == 1) str2 = rdfl->Substring(fore, aft-fore)->Trim();
else {
String ^tmpIntStr = rdfl->Substring(fore, aft-fore)->Trim();
int tmp_int;
if (Int32::TryParse(tmpIntStr, tmp_int)) {
switch (statsRead) {
case 2: int1 = tmp_int; break;
case 3: int2 = tmp_int; break;
}
} else break;
}
++statsRead;
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这通常是一个简单的错误,例如 CONFFILE_NAME 不是完整路径名,并且默认工作目录未设置在您希望的位置。专注于附加调试器。这在 .NET 中很容易,例如在 Main() 方法中使用 System::Diagnostics::Debugger::Launch() 。并为 AppDomain::CurrentDomain->UnhandledException 编写一个事件处理程序,以便异常不会在没有通知的情况下落入位桶中。请务必删除不应该存在的 try/catch 语句。
This is typically a simple mistake, like CONFFILE_NAME not being a full path name and the default working directory not set where you hope it is. Focus on getting a debugger attached. That's easy in .NET, use System::Diagnostics::Debugger::Launch() in your Main() method for example. And write an event handler for AppDomain::CurrentDomain->UnhandledException so that exceptions don't fall in the bit bucket without notice. Be sure to remove try/catch statements that shouldn't be there.