为了读/写SLE4442存储卡,我的应用程序目前正在使用Omnikey Cardman 3021 USB读卡器,一个Sumbsembly智能卡API(外部dll),能够包装CT-API调用(指向omnikey的dll),这样我就可以在我的c#app中读/写存储卡.这里唯一的问题是Omnikey只提供了32位的CT-API.我问他们是否要生产64位版本,但他们不能打扰.
为了使我的应用程序具有64位功能,我必须使用Windows WinSCard API重写它.这里的问题是网上没有具体的例子如何做到这一点.获取工作的APDU命令几乎是不可能的,但我已经设法获得了两个略有不同的版本.几个月来我用谷歌搜索了一百遍,并且我已经设法吞噬了一起,我终于可以阅读SLE4442存储卡了.但是对于我的生活,我无法写作.
我不打算将整个代码发布到第一篇文章中(如果需要,我可以稍后再做,或提供源代码的链接).但我将概述基本步骤.
1)SCardEstablishContext
2)通过SCardListReaders获取读者姓名
3)SCardConnect
4)用SCardTransmit和APDU新字节[] {0xFF,0xB0,0,0,0}读取整个存储器;
5)用SCardTransmit验证引脚和APDU新字节[] {0xFF,0x20,0,0,3,0,0FF,0xFF,0xFF}; (注意,这确实返回0x90; 0x00作为响应,这意味着验证应该是成功的)
6)尝试用ScardTransmit和APDU写新的byte [] {0xFF,0xD6,0,0,50,1}; (尝试在内存位置50写入值1) - 我也尝试使用APDU,第一个参数是0x00和/或第二个字节是0xD0.响应从未是0x90; 0x00因此我假设在写入期间出现错误,但我无法找到返回的错误代码的任何含义.
因为我可以使用WinSCard API读取存储卡,所以必须也可以写入一个(侧面注释 - 我尝试写入的存储卡处于工作状态,我没有将它们锁定未能验证PIN码3次).
1)也许写APDU命令是错误的.可能是指令字节(第二个字节)不正确,或者存储器位置使用某种扩展编码方案.
2)也许验证命令实际上没有验证.因为在命令本身很好,这就是为什么返回0x90,但我必须先调用或设置一些东西.
3)只是预感,但我认为这是真正的罪魁祸首.在谷歌搜索时,我确实发现一些模糊的引用,必须使用参数IOCTL_SMARTCARD_SET_CARD_TYPE调用SCardControl方法并将卡类型设置为SLE4442.但是在任何地方都没有任何工作示例,我的试错法测试导致了失败.我得到"无法正确解释一个或多个提供的参数." 还有一些其他错误信息,不记得它们都是什么.假设我从谷歌代码中复制粘贴的代码具有错误代码的正确描述.
我需要的是有人发布或指导我使用WinSCard API读取/写入SLE4442的c#中具有完整+工作代码的站点,它必须在32位和64位环境中工作.代码不一定是万无一失的 - 例如.很好地处理每个可能的错误情况.我应该能够自己做到这一点.但如果是(包括APDU命令结果描述 - 例如.0x90; 0x00成功,但0x6B; 0x4D是...等......)则更好.
我已经实现了这样的WCF服务:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, ConcurrencyMode = ConcurrencyMode.Single, UseSynchronizationContext=false)]
public sealed class SynchronizationService : ISynchronizationService, IDisposable
{
private MemoryStream objectStream;
...
}
Run Code Online (Sandbox Code Playgroud)
ISyncrhonizationService具有[ServiceContract(SessionMode = SessionMode.Required)].
如果客户端正确通信并最终使用[IsTerminating = true]调用方法,那么我可以很好地处理objectStream变量.如果由于某种原因服务和客户端之间的通信中断,我想自己从服务端清理objectStream变量,这就是我想实现IDisposable接口的原因.但是看一下MSDN文档(http://msdn.microsoft.com/en-us/library/system.idisposable.aspx)我对此有点怀疑,因为根据文档:
// Dispose(bool disposing) executes in two distinct scenarios.
// If disposing equals true, the method has been called directly
// or indirectly by a user's code. Managed and unmanaged resources
// can be disposed.
// If disposing equals false, the method has been called by the
// runtime from inside the …Run Code Online (Sandbox Code Playgroud) 我偶然发现了一个非常奇怪的LINQ to SQL行为/ bug,我无法理解.
我们以下表为例:客户 - >订单 - >详细信息.
每个表都是上一个表的子表,具有常规的主 - 外键关系(1到多个).
如果我执行以下查询:
var q = from c in context.Customers
select (c.Orders.FirstOrDefault() ?? new Order()).Details.Count();
Run Code Online (Sandbox Code Playgroud)
然后我得到一个例外:无法将节点'Value'格式化为SQL执行.
但是以下查询不会抛出异常:
var q = from c in context.Customers
select (c.Orders.FirstOrDefault() ?? new Order()).OrderDateTime;
var q = from c in context.Customers
select (new Order()).Details.Count();
Run Code Online (Sandbox Code Playgroud)
如果我按如下方式更改主查询,则不会出现异常:
var q = from r in context.Customers.ToList()
select (c.Orders.FirstOrDefault() ?? new Order()).Details.Count();
Run Code Online (Sandbox Code Playgroud)
现在我可以理解最后一个查询是有效的,因为以下逻辑:
由于没有"new Order()"到SQL的映射(我在这里猜测),我需要在本地列表上工作.
但我无法理解的是为什么其他两个查询有效?!?
我可能会接受使用context.Customers.ToList()的"本地"版本,但如何加快查询速度?
例如,在上一个查询示例中,我非常确定每个select都会导致执行新的SQL查询以检索Orders.现在我可以通过使用DataLoadOptions来避免延迟加载,但后来我将无缘无故地检索数千个Order行(我只需要第一行)...
如果我可以在一个SQL语句中执行整个查询,因为我想(我的第一个查询示例),那么SQL引擎本身就足够智能,只能为每个客户检索一个Order行...
是否有一种方法可以重写我的原始查询,使其按预期工作并由SQL服务器一次性执行?
编辑:(
阿图罗的更长答案)
我提供的查询纯粹是为了举例.我知道他们自己没有意义,我只是想展示一个简单的例子. …
在任务栏中最小化时,如何(如果可能)将 Vista/Win7 UAC 同意对话框置于前台?
例如,考虑以下场景:
我的应用程序在启动期间检查更新,它下载新的更新文件并通过在 Process.StartInfo 中提供管理员密码来执行它,然后我的应用程序关闭。
此时,如果用户或 Windows 本身设法从 MSI 安装程序窗口失去焦点(可能是通过单击桌面或其他窗口),UAC 会看到该安装程序窗口不是前台窗口,因此会弹出一个闪烁的同意对话框到任务栏。
一些不太聪明的客户不明白我的应用程序尚未完成更新并尝试重新启动应用程序。在这个阶段,我可以枚举正在运行的进程并找到在任务栏中闪烁的consent.exe。
问题是我不能把它带到前台。我尝试使用不同的参数(恢复、显示、正常)从 user32.dll 调用 ShowWindow(),但没有任何反应。我确实检查了 MainWindowHandle 进程,它看起来没问题(它不是零或负数)。我猜测问题在于 UAC 为同意对话框(安全桌面)创建了不同的桌面会话。
如果用户可以点击任务栏中闪烁的图标将同意对话框带到前台,那么应该也可以通过代码来模拟吗?
附注!我正在使用 C#
在我的WPF Window_Loaded事件处理程序中,我有这样的事情:
System.Threading.Tasks.Task.Factory.StartNew(() =>
{
// load data from database
this.Dispatcher.Invoke((Action)delegate
{
// update UI with loaded data
});
});
Run Code Online (Sandbox Code Playgroud)
我想知道的是当用户在从数据库加载数据时以及在运行this.Dispatcher.Invoke例程之前关闭表单时会发生什么?
是否会抛出ObjectDisposedException?或者Dispatcher是否会忽略Invoke例程(当窗口被释放时)?
我试图通过一些基本测试来解决这个问题,但到目前为止我的结果是没有发生任何不好的事情.不会抛出任何异常,应用程序也不会崩溃.
然而,之前我遇到过一些糟糕的经历,当时我使用ThreadPool来实现同样的东西.在Window_Loaded事件处理程序中,我将一个新的用户工作项排入ThreadPool,当数据被加载时我按下了Esc键(我有一个Window_KeyUp事件处理程序侦听Esc键,如果按下它,则调用它.Close( ))并且当应用程序尝试更新UI(Dispatcher.Invoke内部)时应用程序崩溃,因为窗口已经关闭.
因为Task库在后台使用ThreadPool,我担心这可能会再次发生,除非我编写代码来保护我的应用程序......
让我们稍微改变一下场景 - 当用户在Dispatcher.Invoke例程中更新UI时关闭表单会发生什么?
表单结束是否会被推迟,直到Invoke方法返回?或者可以抛出一些异常?
如果有可能抛出异常,如何最好地处理它们?
我能想到的最好的是bool readyToClose = false; 连接一个Window_Closing事件处理程序,它检查是否(!readyToClose)e.Cancel = true; 然后在我更新了我的UI后,我可以设置readyToClose = true,因此如果用户试图过早关闭表单,它将被取消.
或者我应该使用try {...} catch(ObjectDisposedException){//什么都不做}?
我正在使用c#,.net 4,WIX 3.5,Windows Vista.我通过p /调用RegisterApplicationRestart方法并处理WM_QUERYENDSESSION和WM_ENDSESSION窗口消息(我返回new IntPtr(1);)使我的应用程序与RestartManager兼容.
如果我尝试手动更新我的应用程序,那么一切正常:
如果我尝试从应用程序本身更新我的应用程序,那么我遇到了问题:
1)启动申请;
2)下载新的msi文件;
3)使用以下命令启动msi文件:
using (System.Diagnostics.Process p = new System.Diagnostics.Process())
{
p.StartInfo.UseShellExecute = false;
p.StartInfo.FileName = "msiexec";
p.StartInfo.Arguments = "/i \"" + downloadPath + "\" /passive";
p.StartInfo.UserName = "Administrator";
p.StartInfo.Password = securePassword;
p.Start();
}
Run Code Online (Sandbox Code Playgroud)
4)因为我使用的是被动模式,所以应用程序会自动关闭;
5)安装后,我的应用程序没有重新启动,在事件查看器下我有一个
事件10007 - 应用程序或服务"MyApp"无法重新启动.
我试过了:
但上述都没有奏效(总是相同的结果).
必须以提升的权限启动设置可能与问题有关,因为在手动更新期间,我在事件查看器中收到警告 - 应用程序MyApp(pid 3220)无法重新启动 - 应用程序SID与Conductor SID不匹配.
尽管如此,重新启动应用程序仍然有效.谷歌警告不会产生任何好的/特定的结果,只是这个警告可能是由于在提示的提示中运行msi引起的.
如何修复(或解决)此问题,以便我可以从应用程序本身更新我的应用程序并在之后重新启动我的应用程序?
编辑 - 额外测试:
p.StartInfo.LoadUserProfile = …我需要帮助将以下 netTcpBinding 转换为等效的 CustomBinding:
<bindings>
<netTcpBinding>
<binding name="secureNetTcp" openTimeout="00:00:25" closeTimeout="00:00:27" receiveTimeout="00:10:10" sendTimeout="00:01:00"
listenBacklog="50" maxBufferPoolSize="2097152" maxBufferSize="2097152" maxConnections="50" maxReceivedMessageSize="2097152">
<readerQuotas maxArrayLength="2097152" />
<reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="true" />
<security mode="TransportWithMessageCredential">
<message algorithmSuite="Basic256Sha256" />
</security>
</binding>
</netTcpBinding>
</bindings>
Run Code Online (Sandbox Code Playgroud)
我主要是在自定义绑定的安全部分苦苦挣扎,因为我无法理解所有不同的设置。并且一切似乎也以不同的方式命名(与 netTcpBinding 参数相比)。
如果有必要,我还将提供以下信息:
服务端点通过serviceBehavior附加了一个证书。
在我的代码中,我在创建代理时提供了用户名/密码(服务行为<userNameAuthentication userNamePasswordValidationMode="Windows" />在serviceCredentials下;对于 netTcpBinding,WCF 配置编辑器显示ClientCredentialType=Windows,我猜这是默认值)。
更新:
我为我的主要问题找到了一个潜在的解决方案 - 增加ChannelInitilizationTimeout - 无需创建自定义绑定。我会分享这个,以防有人在谷歌搜索时绊倒这个线程......
我所做的是创建一个从NetTcpBinding继承的自定义类,并在它的构造函数中使用反射来设置ChannelInitilizationTimeout属性。从而保持与NetTcpBinding 的完全兼容性。
这是我的自定义类的代码:
public class MyNetTcpBinding : NetTcpBinding
{
public MyNetTcpBinding()
{
var fi = …Run Code Online (Sandbox Code Playgroud) 我正在使用 Visual Studio 2022。我创建了一个 .net 6 项目。我添加了 COM 引用:Microsoft Excel 16 对象库(Microsoft.Office.Interop.Excel) 和Microsoft Office 16 对象库(Microsoft.Office.Core)。
以下 Excel 互操作代码行抛出错误at SetElement(),无法构建:
Chart c = (Chart)wbSheets.Application.Workbooks[1].Charts.Add();
chart.SetElement(Microsoft.Office.Core.MsoChartElementType.msoElementChartTitleAboveChart);
Run Code Online (Sandbox Code Playgroud)
Microsoft.Office.Core... 在未引用的程序集中定义。您必须添加对 Assembly Office 的引用,Version=15.0.0.0, ..., PublicKeyToken=71e9bce111e9429c
一个非常奇怪的错误,Office 16 (Office 2016) 库需要引用 Office 15 (Office 2013)。
COM 引用和 C# 代码的完全相同的步骤在 .NET 4.8 Framework 中完美运行。因此,该问题特定于 .NET 6(可能是 .NET 5 和所有以前的 .NET Core 版本)。
使用 nuget 命令Install-Package MicrosoftOfficeCore -Version 15.0.0安装引用并手动删除以前的 v16 引用,确实解决了代码构建错误。但现在该依赖项有一个黄色三角形警告,该依赖项适用于 .NET 4.6-4.8 Framework,可能与 .NET 6 不兼容。
尽管如此,代码似乎可以工作并且生成了 …
我有一个巨大的复杂的LINQ to SQL查询,我需要以某种方式进行优化,因为后台C#编译器完全占用CPU而我无法.cs在Visual Studio 2010中正常输入或编辑我的文件(每个字母,特别是如果IntelliSense想要弹出,可怕地滞后).
罪魁祸首是这样的:
var custFVC =
(from cfvc in customer.CustomerFrameVariationCategories
let lastValue = cfvc.CustomerFrameVariationCategoryValueChanges.Where(cfvcvc => cfvcvc.ChangeDateTime <= this.SelectedDateTime).OrderByDescending(cfvcvc2 => cfvcvc2.ChangeDateTime).FirstOrDefault() ?? new CustomerFrameVariationCategoryValueChange()
let lastValue2 = cfvc.FrameVariationCategory.FrameVariation.Frame.FrameValueChanges.Where(fvc => fvc.ChangeDateTime <= this.SelectedDateTime).OrderByDescending(fvc2 => fvc2.ChangeDateTime).FirstOrDefault() ?? new FrameValueChange()
let lastValue3 = cfvc.FrameVariationCategory.FrameVariationCategoryValueChanges.Where(fvcvc => fvcvc.ChangeDateTime <= this.SelectedDateTime).OrderByDescending(fvcvc2 => fvcvc2.ChangeDateTime).FirstOrDefault() ?? new FrameVariationCategoryValueChange()
let lastValue4 = cfvc.FrameVariationCategory.FrameVariation.FrameVariationModules.Any(fvm => (fvm.FrameModule.FrameModuleValueChanges.Where(fmvc => fmvc.ChangeDateTime <= this.SelectedDateTime).OrderByDescending(fmvc2 => fmvc2.ChangeDateTime).FirstOrDefault() ?? new FrameModuleValueChange()).IsActive == false)
where lastValue.IsActive == true
orderby cfvc.FrameVariationCategory.FrameVariation.Frame.Name, cfvc.FrameVariationCategory.Category.Name, cfvc.FrameVariationCategory.FrameVariation.Name
select …Run Code Online (Sandbox Code Playgroud) 我将设置此问题并亲自回答,以便其他人可以轻松地搜索并找到正确的答案。我不得不谷歌搜索几个小时,并从多个来源汇编最终结果...
因此,问题是- 如何在ClickOnce场景(特别是WPF,特别是c#)中启用Per-Monitor v2 DPI感知?
在Win 10 Creators Update(1703)中添加了Per-monitor v2。众所周知,ClickOnce不支持在app.manifest文件中声明的DPI感知,例如。
我无法找到正确的语法,以便使用await with lambda表达式(匿名lambda方法).所有示例似乎都使用了使用async关键字声明的实际方法.让我来描述我想要的东西:
...code in UI thread...
Customer cust = null;
using (DataContext context = new DataContext()) // I want to run this async
{
cust = context.Customers.Single(c => c.Id == 1);
}
...continue code in UI thread...
Run Code Online (Sandbox Code Playgroud)
为了在数据库查询期间不阻塞UI线程,我会写:
...code in UI thread...
Customer cust = null;
Task.Run(() =>
{
using (DataContext context = new DataContext())
{
cust = context.Customers.Single(c => c.Id == 1);
}
});
...continue code in UI thread...
Run Code Online (Sandbox Code Playgroud)
当然,这不起作用,因为UI线程将在任务启动后继续.我不能Wait()上Task,因为这会阻止用户界面线程.简单地await在前面添加Task.Run()不编译.我能想到的最好的事情是: …
c# ×6
.net ×2
wcf ×2
wpf ×2
.net-4.0 ×1
.net-6.0 ×1
async-await ×1
c#-5.0 ×1
clickonce ×1
dpi ×1
linq ×1
linq-to-sql ×1
performance ×1
uac ×1
wix ×1