将程序集清单直接加载到应用程序上下文中是否正确?(Is it correct to load the assembly manifest directly into the application context?)
我正在尝试使用免注册COM来运行一个相当纠结的方案。
并不是它不起作用,而是我遇到了一种令人困惑的情况,我似乎应该直接在应用程序上下文中激活程序集依赖关系的清单,而不是让应用程序上下文指向依赖程序集。
通常,您有一个应用程序,一个应用程序清单,一个(server-)dll和它的程序集清单。 这些对应于示例给出的内容 :
- client.exe
- client.exe.manifest(这个指向 SideBySide.X作为
dependentAssembly
)- SideBySide.dll
- SideBySide.X.manifest
现在,一个标准情况是将客户端应用程序清单嵌入客户端可执行文件中,然后使用DLL及其外部清单文件。
现在,如果由于某种原因在编译时未知正确的应用程序清单,您可以通过Activation Context API在运行时加载清单文件。
这就是令人困惑的地方:
根据文章,客户端应用程序现在直接将其激活上下文切换到程序集清单:
如果你查看client.cpp中的_tmain函数...初始化激活上下文的新代码段如下:
actCtx.lpSource = "SideBySide.X.manifest";
我已经交叉检查了这个,它也可以动态加载包含来自
client.exe.manifest
的信息的文件,即只是对SideBySide.X的引用,并继续这个激活上下文 - 这也对应于ActCtx在我们将正确的应用程序清单嵌入可执行文件时使用。也就是说,
actCtx.lpSource = "client.exe.manifest";
也会奏效。TL; DR在应用程序代码中直接激活“包含” 程序集清单的激活上下文(如果有)的含义是什么。
这是从文件加载清单时应该如何完成的? (如果是这样,为什么我们不能直接将汇编清单嵌入到可执行文件中,当它在编译时已知。)
注意 :(这应该是对@Eric Brown答案的评论,但它变得相当冗长)
链接的文章在解释两个
RT_MANIFEST
资源类型方面做得不错,但是对于regFreeCOm,它留下了一些松散的结尾。 我会抛出一些跳到我身边的引号:ISOLATIONAWARE_MANIFEST_RESOURCE_ID主要用于DLL。 如果dll需要除进程默认值之外的私有依赖项,则应该使用它。 ... NT库加载器检查dll是否具有RT_MANIFEST类型的资源,ID ISOLATIONAWARE_MANIFEST_RESOURCE_ID。 如果是,则加载程序使用资源调用CreateActCtx,并使用生成的激活上下文来探测dll的静态依赖项 。
我理解这意味着
RT_MANIFEST/2
的唯一要点是静态 DLL依赖加载器找到用于解析DLL依赖关系的正确资源。 ( 不是 COM依赖项,请参阅下文。)有时,您希望在探测dll的静态依赖项之外使用激活上下文。 编译模块时,可以定义宏ISOLATION_AWARE_ENABLED。
定义ISOLATION_AWARE_ENABLED后,Windows会重新定义某些API。 例如,LoadLibraryExW被重新定义为IsolationAwareLoadLibraryExW。
...并非所有受激活上下文影响的API都会被包装。 例如,......, 也不是任何COM API 。
总而言之:我认为RT_MANIFEST机制主要与regFreeCOM正交,因为COM根本不关心激活上下文的来源,并且没有regFreeCOM wrt的内置帮助。 隔离意识。
I'm currently trying to get a rather tangled scheme running with registration free COM.
It's not that it is not working, it's that I have hit a kind of confusing situation, where it seems I should active the manifest of the assembly dependency directly in the application context, rather than have the application context point at the dependent assembly.
It is rather easy to explain by the example project MS themselves publish:
Normally, you have an application, an app manifest, a (server-)dll and it's assembly manifest. These correspond to what the example gives:
- client.exe
- client.exe.manifest (This one points to SideBySide.X as
dependentAssembly
)- SideBySide.dll
- SideBySide.X.manifest
Now, one standard case is to embed the client application manifest inside the client executable, and then use the DLL and its external manifest file.
Now, if for whatever reason the correct application manifest isn't known at compile time, you can load a manifest file at runtime via the Activation Context API.
And this is where it gets confusing:
According to the article, the client application now directly switches its Activation Context to the assembly manifest:
If you look at the _tmain function in client.cpp ... a new section of code that initializes the activation context as follows:
actCtx.lpSource = "SideBySide.X.manifest";
I have cross checked this, and it would also work to dynamically load a file that contains the info from
client.exe.manifest
, i.e. just the reference to SideBySide.X, and continue with this Activation Context - which would also correspond to the ActCtx in use when we embed a correct application manifest into the executable.That is,
actCtx.lpSource = "client.exe.manifest";
would also work.TL;DR What is the implication, if any, of directly activating an Activation Context "containing" an assembly manifest inside application code.
Is this how it's supposed to be done when loading manifests from files? (And if so, why can't we directly embed the assembly manifest into the executable, when it is known at compile time.)
Note: (This should really be a comment to @Eric Brown's answer, but it's getting rather lengthy)
The linked article does a decent job of explaining the two
RT_MANIFEST
resource types, but with regard to regFreeCOm, it leaves a few loose ends. I'll throw in some quotes that jumped at me:ISOLATIONAWARE_MANIFEST_RESOURCE_ID is used primarily for DLLs. It should be used if the dll wants private dependencies other than the process default. ... the NT library loader checks to see if the dll has a resource of type RT_MANIFEST, ID ISOLATIONAWARE_MANIFEST_RESOURCE_ID. If it does, the loader calls CreateActCtx with the resource, and use the generated activation context to probe the dll's static dependencies.
What I understand this to mean is that the only point of
RT_MANIFEST/2
is for the static DLL dependency loader to find the correct resource to use for resolving DLL dependencies. (Not COM dependencies, see below.)Sometimes, you want to use the activation context outside of probing the dll's static dependencies. You can define macro ISOLATION_AWARE_ENABLED when you compile the module.
When ISOLATION_AWARE_ENABLED is defined, Windows re-defines certain APIs. For example LoadLibraryExW is redefined to IsolationAwareLoadLibraryExW.
... Not all APIs affected by activation context are wrapped. For example, ..., and neither is any of the COM APIs.
So, to sum up: I think the RT_MANIFEST mechanism is mostly orthogonal to regFreeCOM as COM doesn't care at all where it's activation context comes from and there is no built-in help for regFreeCOM wrt. Isolation Awareness.
原文:https://stackoverflow.com/questions/19381348
最满意答案
=CountIF(C2:C32,"<>"&"")
应该做你想做的事情。
对于多个页面,请为每个页面示例执行countIf -
=CountIF('Sheet1'!C2:C32,"<>"&"")+CountIF('Sheet2'!C2:C32,"<>"&"")
这将为您提供具有值的单元格的数量,如果您想要将这些值一起添加,请在您的问题中指定并且我可以修复答案
=CountIF(C2:C32,"<>"&"")
should do what you want.
For multiple pages, do a countIf for each page example -
=CountIF('Sheet1'!C2:C32,"<>"&"")+CountIF('Sheet2'!C2:C32,"<>"&"")
This will work to give you the number of cells with values, if you want to add the values together please specify that in your question and I can fix the answer
相关问答
更多-
我重写了你的代码 你声明了一些工作表对象,但你没有使用它们 列的指针搞砸了名字 _numRows = _行分为两部分 我还没有测试过您的代码,但是看起来没问题 一件事......如果两列中的大量数据,代码可能需要很长时间才能运行 我将代码更改为复制到J列中与K列相同的行 Sub IndustryMatch() Dim wBk As Workbook Set wBk = ActiveWorkbook Dim dbSht As Worksheet Set dbSht = wB ...
-
您只需要添加工作表名称: If ws.Name <> "Uptime" Then With Worksheets("Uptime").Cells(Rows.Count, 1).End(xlUp).Offset(1, 0) .Value2 = ws.Name .Offset(, 1).Formula = "=('" & ws.name & "'!ET40/60)/24" End With You just need to add in the sheet name: If w ...
-
=CountIF(C2:C32,"<>"&"") 应该做你想做的事情。 对于多个页面,请为每个页面示例执行countIf - =CountIF('Sheet1'!C2:C32,"<>"&"")+CountIF('Sheet2'!C2:C32,"<>"&"") 这将为您提供具有值的单元格的数量,如果您想要将这些值一起添加,请在您的问题中指定并且我可以修复答案 =CountIF(C2:C32,"<>"&"") should do what you want. For multiple pages, d ...
-
通过引用多个工作表的VBA编写SUMIF问题(Issue With Writing SUMIF via VBA That References Multiple Worksheets)[2024-05-08]
我认为你的问题可能是引用和错误对象的混合。 我已经修复了您的尺寸标注 我已经将FormulaR1C1的对象引用更改为Formula 我改变了公式中的引号(有额外的双引号) Dim wsDummy As Worksheet Set wsDummy = Worksheets("Dummy Sheet One") Dim wsOrderNumber As Worksheet Set wsOrderNumber = Worksheets("Order Number") wsOrderNumber.Cells(2 ... -
控制excel公式存在于一个工作表的多个工作表中(Controlling excel formula exists in multiple worksheets from one sheet)[2020-01-03]
如果要在同一工作簿中的多个工作表中更改特定单元格,可以按如下方式进行“3D”选择: 通过Shift或Ctrl键选择要更新的工作表 - 单击以选择所需的选项卡。 您还可以右键单击工作表选项卡,然后从上下文菜单中选择“ Select All Sheets ”以选择工作簿中的所有工作表。 选择后,工作表标签变为白色。 在当前可见的工作表上,更改所需的单元格(例如D10 )。 然后,在您选择的所有工作表中复制更改。 (可选)不要忘记再次取消选中所有工作表以避免意外更改它们,方法是单击当前可见Ungroup Shee ... -
我将提供将这个组合在一起所需的逻辑和所有参考资料; 并会让你尝试把它放在一起:)。 如果需要,请回来寻求更多帮助。 您需要遍历工作簿中的所有工作表( Microsoft教程 ) 您需要找到给定列的最后一行( 在线教程 ) 您需要使用IF语句来选择要使用的公式( MSDN参考 ) UPDATE 您的代码有什么问题: Range(J2) = Formula = ((EndCell.Row) * (0.1)) 你告诉电脑的是: 将EndCell.Row乘以0.1(其中包含C列中最后一个单元格下方和右侧的行数) ...
-
你只是远离目标的一个参考: Sub ConcatForm() Dim wSht As Worksheet lastRow = Range("M" & Rows.count).End(xlUp).row '<--| without explicit worksheet qualification it will reference a range in the "active" sheet Application.ScreenUpdating = False For Each ...
-
作为评论的后续行动,这个有效: Worksheets("Sheet1").Cells(ptr, out).Formula = "=VLookup(""" & val & """,'" & sheetname1 & "'!" & Worksheets(sheetname1).Range(start_range, end_range).Address & "," & Hincrement & ", False)" As follow up from comments, this one works: Work ...
-
你指的是表单本身,而不是它的名字。 尝试: .Range("G2:G" & OutputLastRow).Formula = _ "=VLOOKUP(A2,'" & sourceSheet.Name & "'!$A$2:$B$" & SourceLastRow & ",2,0)" You're referring to the sheet itself, not it's name. Try: .Range("G2:G" & OutputLastRow).Formula = _ ...
-
通过excel中的多个工作表删除单元格的代码更快(Faster code to delete cells through multiple worksheets in excel)[2024-05-05]
尝试将要删除的所有Range合并到MergeRng对象,然后立即将其全部删除。 码 Sub DataDeleteStage1() ScreenUpdating = False Dim lrow As Long Dim ws As Worksheet Dim icntr As Long Dim MergeRng As Range For Each ws In ThisWorkbook.Worksheets With ws lrow = .Cells(.Rows.Count, "A ...