- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我什至不确定这是否适用于 Windows;我还没有看到一个人要求这么普遍的东西并找到解决方案。这可能是可能的,但可能没有用于处理它的 API。
我有一个自动化测试模块,我正在为 Windows 工作,它使用一个模块以通用方式处理检测到的 EXE,除非它检测到二进制文件来自特定的测试框架。到目前为止,我只能通过查询帮助和处理响应/字符串解析来做到这一点。如果我触发某人在框架之外编写的长时间测试,该测试接受命令行参数寻求帮助,但实际上并不处理这些命令行参数而只是自动运行,这可能会导致问题。因此,有时我会卡在等待测试完成的时候,而不是进行闪电般的快速查询。这就是我试图通过这个花哨的新模块避免的。 :)
这个问题的关键是,这个用于获取 DLL 列表的消耗模块将分发到非开发 Windows 系统,我不能说它是用什么构建的(.NET、C++ 等)。这使我无法使用 dumpbin
和 link
作为微软 does not allow them to be distributed .出于我自己的许可要求,我的这个模块不会出售;永远的免费软件。
我被建议调查 dumpbin
在我意识到我无法分发它之前。当我使用它时,这就是我得到的:
c:\test_dir>dumpbin /dependents .\qt_unit_test.exe
Microsoft (R) COFF/PE Dumper Version 14.00.24215.1
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file .\qt_test_unit_test.exe
File Type: EXECUTABLE IMAGE
Image has the following dependencies:
Qt5Test.dll
Qt5Core.dll
KERNEL32.dll
VCRUNTIME140.dll
api-ms-win-crt-utility-l1-1-0.dll
api-ms-win-crt-runtime-l1-1-0.dll
api-ms-win-crt-math-l1-1-0.dll
api-ms-win-crt-stdio-l1-1-0.dll
api-ms-win-crt-locale-l1-1-0.dll
api-ms-win-crt-heap-l1-1-0.dll
Summary
1000 .data
1000 .gfids
1000 .pdata
2000 .rdata
1000 .reloc
1000 .rsrc
1000 .text
c:\test_dir>dumpbin /dependents .\qt_unit_test.exe | call findstr /i qt5test 1>nul 2>nul
c:\test_dir>if "%errorlevel%"=="0" echo is Qt Test
Assembly.GetReferencedAssemblies
,但这当然只能获取程序集信息,因此常规的旧 STL C++ 应用程序会生成异常。
IntPtr
翻译到一个字符串或字符串列表,告诉您哪些 DLL 用于它。看起来它在其他方面工作正常,但是是的,经典
voodoo programming场景在这里...
6.4. The .idata Section All image files that import symbols, including virtually all executable (EXE) files, have an .idata section. A typical file layout for the import information follows...
.idata
的同时为了处理这个问题,我遇到了一个讨厌的小问题。
idata
的“几乎所有可执行文件...”子句部分并不像文档会让您相信的那样包罗万象。查看 Windows 10 内置的 Calculator.exe 应用程序:
C:\WINDOWS\system32>dumpbin /summary "C:\Program Files\WindowsApps\Microsoft.WindowsCalculator_10.1703.601.0_x64__8wekyb3d8bbwe\Calculator.exe"
Microsoft (R) COFF/PE Dumper Version 14.00.24215.1
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file C:\Program Files\WindowsApps\Microsoft.WindowsCalculator_10.1703.601.0_x64__8wekyb3d8bbwe\Calculator.exe
File Type: EXECUTABLE IMAGE
Summary
4C000 .data
1000 .gfids
1000 .giats
21000 .pdata
135000 .rdata
A000 .reloc
1000 .rsrc
20D000 .text
1000 .tls
1000 minATL
.idata
部分。但是,这并不能阻止 dumpbin 找到这些依赖项:
C:\WINDOWS\system32>dumpbin /dependents "C:\Program Files\WindowsApps\Microsoft.WindowsCalculator_10.1703.601.0_x64__8wekyb3d8bbwe\Calculator.exe"
Microsoft (R) COFF/PE Dumper Version 14.00.24215.1
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file C:\Program Files\WindowsApps\Microsoft.WindowsCalculator_10.1703.601.0_x64__8wekyb3d8bbwe\Calculator.exe
File Type: EXECUTABLE IMAGE
Image has the following dependencies:
api-ms-win-core-localization-l1-2-1.dll
api-ms-win-eventing-provider-l1-1-0.dll
api-ms-win-core-com-l1-1-1.dll
api-ms-win-core-sysinfo-l1-2-1.dll
api-ms-win-core-processthreads-l1-1-2.dll
api-ms-win-core-sysinfo-l1-2-3.dll
vccorlib140_app.DLL
MSVCP140_APP.dll
CONCRT140_APP.dll
VCRUNTIME140_APP.dll
api-ms-win-crt-runtime-l1-1-0.dll
api-ms-win-crt-convert-l1-1-0.dll
api-ms-win-crt-string-l1-1-0.dll
api-ms-win-crt-heap-l1-1-0.dll
api-ms-win-crt-stdio-l1-1-0.dll
api-ms-win-crt-math-l1-1-0.dll
api-ms-win-crt-locale-l1-1-0.dll
api-ms-win-core-util-l1-1-0.dll
api-ms-win-core-synch-l1-2-0.dll
api-ms-win-core-winrt-error-l1-1-1.dll
api-ms-win-core-winrt-string-l1-1-0.dll
api-ms-win-core-handle-l1-1-0.dll
api-ms-win-core-winrt-l1-1-0.dll
api-ms-win-core-profile-l1-1-0.dll
api-ms-win-core-libraryloader-l1-2-0.dll
api-ms-win-core-interlocked-l1-2-0.dll
Summary
4C000 .data
1000 .gfids
1000 .giats
21000 .pdata
135000 .rdata
A000 .reloc
1000 .rsrc
20D000 .text
1000 .tls
1000 minATL
//******************************************************************************
// HEADERS
#include "Windows.h"
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <vector>
#include <experimental\filesystem>
//******************************************************************************
// NAMESPACES
namespace fs = std::experimental::filesystem;
//******************************************************************************
//FUNCTION DECLARATIONS
bool verify_image_file(std::string);
std::vector<char> read_all_bytes(const char* file);
std::vector<std::string> parse_file(std::string file);
//******************************************************************************
// CONSTANTS
// LABEL HEX DEC
//
const WORD MAGIC_NUM_32BIT = static_cast<const WORD>(0x10b); // 267
const WORD MAGIC_NUM_64BIT = static_cast<const WORD>(0x20b); // 523
const int IMG_SIGNATURE_OFFSET = static_cast<const int>(0x3c); // 60
const int IMPORT_TABLE_OFFSET_32 = static_cast<const int>(0x68); // 104
const int IMPORT_TABLE_OFFSET_64 = static_cast<const int>(0x78); // 120
const int IMG_SIGNATURE_SIZE = static_cast<const int>(0x4); // 4
const int OPT_HEADER_OFFSET_32 = static_cast<const int>(0x1c); // 28
const int OPT_HEADER_OFFSET_64 = static_cast<const int>(0x18); // 24
const int DATA_DIR_OFFSET_32 = static_cast<const int>(0x60); // 96
const int DATA_DIR_OFFSET_64 = static_cast<const int>(0x70); // 112
const int DATA_IAT_OFFSET_64 = static_cast<const int>(0xD0); // 208
const int DATA_IAT_OFFSET_32 = static_cast<const int>(0xC0); // 192
const int SZ_OPT_HEADER_OFFSET = static_cast<const int>(0x10); // 16
const int RVA_AMOUNT_OFFSET_64 = static_cast<const int>(0x6c); // 108
const int RVA_AMOUNT_OFFSET_32 = static_cast<const int>(0x5c); // 92
const char * KNOWN_IMG_SIGNATURE = static_cast<const char*>("PE\0\0");
//******************************************************************************
// Globals
bool is64Bit = false;
bool is32Bit = false;
//******************************************************************************
// PLACEHOLDERS
const char* ph_file("C:\\Windows\\System32\\notepad.exe");
//******************************************************************************
// ENTRY
int main(int argc, char* argv[])
{
if (!verify_image_file(ph_file))return -1;
if (parse_file(ph_file).size() > 1)return 0;
else return -1;
return -1;
}
//******************************************************************************
// FILE PARSER
std::vector<std::string> parse_file(std::string file)
{
std::vector<char> bytes = read_all_bytes(file.c_str());
std::vector<std::string> dependencies;
DWORD * signature_offset_location = (DWORD*)&bytes[IMG_SIGNATURE_OFFSET];
char * signature = (char*)&bytes[*signature_offset_location];
if (*signature != *KNOWN_IMG_SIGNATURE)return dependencies;
DWORD coff_file_header_offset = *signature_offset_location + IMG_SIGNATURE_SIZE;
IMAGE_FILE_HEADER* coff_file_header = (IMAGE_FILE_HEADER*)&bytes[coff_file_header_offset];
DWORD optional_file_header_offset = coff_file_header_offset + sizeof(IMAGE_FILE_HEADER);
WORD size_of_optional_header_offset = coff_file_header_offset + SZ_OPT_HEADER_OFFSET;
WORD* size_of_optional_header = (WORD*)&bytes[size_of_optional_header_offset];
//Magic is a 2-Byte value at offset-zero of the optional file header regardless of 32/64 bit
WORD* magic_number = (WORD*)&bytes[optional_file_header_offset];
if (*magic_number == MAGIC_NUM_32BIT)is32Bit = true;
else if (*magic_number == MAGIC_NUM_64BIT)is64Bit = true;
else
{
std::cerr << "Could not parse magic number for 32 or 64-bit PE-format Image File." << std::endl;
return dependencies;
}
if (is64Bit)
{
IMAGE_OPTIONAL_HEADER64 * img_opt_header_64 = (IMAGE_OPTIONAL_HEADER64*)&bytes[optional_file_header_offset];
IMAGE_DATA_DIRECTORY* import_table_data_dir = (IMAGE_DATA_DIRECTORY*)&bytes[optional_file_header_offset + IMPORT_TABLE_OFFSET_64];
DWORD* import_table_address = (DWORD*)import_table_data_dir;
// To Get the import table, you need to check all the IMAGE_SECTION_HEADERs for the section that matches size of the direct-query.
// TO get those you can use normal offsets. To go further, we need to start using the RVA
// IMAGE_SECTION_HEADERS starts directly after the end of the optional file header for file_header->NumberOfSections
// Then, your RVA is if (ptr_to_raw_data >= va && ptr_to_raw_data < va + SizeOfData){//isSection}
// DWORD FileOffset = Ptr_To_Raw_Data - VA + PointerToRawData
DWORD image_section_header_offset = optional_file_header_offset;
for (int i = 0; i < coff_file_header->NumberOfSections; i++)
{
IMAGE_SECTION_HEADER* queried_section_header = (IMAGE_SECTION_HEADER*)&bytes[image_section_header_offset];
if (queried_section_header->PointerToRawData >= import_table_data_dir->VirtualAddress && (queried_section_header->PointerToRawData < (import_table_data_dir->VirtualAddress + queried_section_header->SizeOfRawData)))
{
DWORD import_table_offset = queried_section_header->PointerToRawData - import_table_data_dir->VirtualAddress + queried_section_header->PointerToRawData;
IMAGE_IMPORT_DESCRIPTOR* import_table_descriptor = (IMAGE_IMPORT_DESCRIPTOR*)&bytes[import_table_offset];
if (import_table_descriptor->Name==NULL &&
import_table_descriptor->Characteristics==NULL &&
import_table_descriptor->FirstThunk==NULL &&
import_table_descriptor->ForwarderChain==NULL &&
import_table_descriptor->OriginalFirstThunk==NULL &&
import_table_descriptor->TimeDateStamp==NULL)
{
break;//Signifies end of IMAGE_IMPORT_DESCRIPTORs
}
DWORD* dependency_name_address = (DWORD*)import_table_descriptor->Name;
char * dependency_name = (char *)&bytes[import_table_descriptor->Name];
dependencies.push_back((std::string)dependency_name);
int breakpoint = 0;
}
image_section_header_offset = image_section_header_offset + sizeof(IMAGE_SECTION_HEADER);
}
}
else//32-bit behavior
{
//todo
}
return dependencies;
}
//******************************************************************************
// FILE READER
std::vector<char> read_all_bytes(const char* filename)
{
std::ifstream ifs(filename, std::ios::binary | std::ios::ate);
std::ifstream::pos_type pos = ifs.tellg();
std::vector<char> result(pos);
ifs.seekg(0, std::ios::beg);
ifs.read(&result[0], pos);
return result;
}
//******************************************************************************
// IMAGE-TYPE FILE VERIFIER
bool verify_image_file(std::string file_to_verify)
{
if (fs::exists(file_to_verify))
{
size_t extension_query = file_to_verify.find(".dll", 0);
if (extension_query == std::string::npos)
{
extension_query = file_to_verify.find(".DLL", 0);
if (extension_query == std::string::npos)
{
extension_query = file_to_verify.find(".exe", 0);
if (extension_query == std::string::npos)
{
extension_query = file_to_verify.find(".EXE", 0);
}
else { return true; }
if (extension_query != std::string::npos) { return true; }
}
else { return true; }
}
else { return true; }
}
return false;
}
最佳答案
未优化的 POC 代码,针对 x86 和 x64 进行测试
主要使用指针数学而不是访问器,很少使用 Windows.h
和 winnt.h
-- 所有内容都应该包含在为 2017 安装的 Visual C++ Redists 中。如果您想要早期版本,则必须删除 Visual C++ 2017 功能,这些功能除了文件系统帮助程序之外没什么可说的。
//******************************************************************************
// Headers
#include "Windows.h"
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <vector>
#include <experimental\filesystem>
//******************************************************************************
// Namespaces
namespace fs = std::experimental::filesystem;
//******************************************************************************
//FUNCTION DECLARATIONS
bool verify_image_file(std::string);
std::vector<char> read_all_bytes(const char* file);
std::vector<std::string> parse_pe_import_table_names(std::string file);
//******************************************************************************
// Constants
// LABEL HEX DEC
//
const WORD MAGIC_NUM_32BIT = static_cast<const WORD>(0x10b); // 267
const WORD MAGIC_NUM_64BIT = static_cast<const WORD>(0x20b); // 523
const int IMG_SIGNATURE_OFFSET = static_cast<const int>(0x3c); // 60
const int IMPORT_TABLE_OFFSET_32 = static_cast<const int>(0x68); // 104
const int IMPORT_TABLE_OFFSET_64 = static_cast<const int>(0x78); // 120
const int IMG_SIGNATURE_SIZE = static_cast<const int>(0x4); // 4
const int OPT_HEADER_OFFSET_32 = static_cast<const int>(0x1c); // 28
const int OPT_HEADER_OFFSET_64 = static_cast<const int>(0x18); // 24
const int DATA_DIR_OFFSET_32 = static_cast<const int>(0x60); // 96
const int DATA_DIR_OFFSET_64 = static_cast<const int>(0x70); // 112
const int DATA_IAT_OFFSET_64 = static_cast<const int>(0xD0); // 208
const int DATA_IAT_OFFSET_32 = static_cast<const int>(0xC0); // 192
const int SZ_OPT_HEADER_OFFSET = static_cast<const int>(0x10); // 16
const int RVA_AMOUNT_OFFSET_64 = static_cast<const int>(0x6c); // 108
const int RVA_AMOUNT_OFFSET_32 = static_cast<const int>(0x5c); // 92
const char * KNOWN_IMG_SIGNATURE = static_cast<const char*>("PE\0\0");
//******************************************************************************
// Globals
bool is64Bit = false;
bool is32Bit = false;
//******************************************************************************
// Exceptions
class invalid_parameters : public std::exception { const char* what() const throw()
{ return "You did not provide the solitary command-line parameter of the EXE or DLL to check.\n"; } };
class invalid_image_file : public std::exception { const char* what() const throw()
{ return "The file detected was not determined to be an image file based off its extension.\n"; } };
class unexpected_rva_offset : public std::exception { const char* what() const throw()
{ return "An unexpected value was returned for the RVA to File Offset.\n"; } };
class non_image_magic_number : public std::exception { const char* what() const throw()
{ return "The PE Optional Header's Magic Number did not indicate the file was an image.\n"; } };
class invalid_pe_signature : public std::exception { const char* what() const throw()
{ return "The PE Signature was not detected.\n"; } };
//******************************************************************************
// Entry
int main(int argc, char* argv[])
{
if (argc != 2)throw invalid_parameters();
const char* param_one = (const char*)argv[1];
if (!verify_image_file(argv[1])) { throw invalid_image_file(); }
std::vector<std::string> static_import_dependencies = parse_pe_import_table_names(argv[1]);
if (static_import_dependencies.size() > 1)
{
for (int i = 0; i < (static_import_dependencies.size()-1);i++)
{
std::cout << static_import_dependencies[i] << std::endl;
}
return 0;
}
else return -1;
return -1;
}
//******************************************************************************
// PE Parser
std::vector<std::string> parse_pe_import_table_names(std::string file)
{
std::vector<char> bytes = read_all_bytes(file.c_str());
std::vector<std::string> dependencies;
DWORD * signature_offset_location = (DWORD*)&bytes[IMG_SIGNATURE_OFFSET];
char * signature = (char*)&bytes[*signature_offset_location];
if (*signature != *KNOWN_IMG_SIGNATURE)return dependencies;
DWORD coff_file_header_offset = *signature_offset_location + IMG_SIGNATURE_SIZE;
IMAGE_FILE_HEADER* coff_file_header = (IMAGE_FILE_HEADER*)&bytes[coff_file_header_offset];
DWORD optional_file_header_offset = coff_file_header_offset + sizeof(IMAGE_FILE_HEADER);
WORD size_of_optional_header_offset = coff_file_header_offset + SZ_OPT_HEADER_OFFSET;
WORD* size_of_optional_header = (WORD*)&bytes[size_of_optional_header_offset];
//Magic is a 2-Byte value at offset-zero of the optional file header regardless of 32/64 bit
WORD* magic_number = (WORD*)&bytes[optional_file_header_offset];
if (*magic_number == MAGIC_NUM_32BIT)is32Bit = true;
else if (*magic_number == MAGIC_NUM_64BIT)is64Bit = true;
else
{
std::cerr << "Could not parse magic number for 32 or 64-bit PE-format Image File." << std::endl;
return dependencies;
}
if (is64Bit)
{
IMAGE_OPTIONAL_HEADER64 * img_opt_header_64 = (IMAGE_OPTIONAL_HEADER64*)&bytes[optional_file_header_offset];
IMAGE_DATA_DIRECTORY* import_table_data_dir = (IMAGE_DATA_DIRECTORY*)&bytes[optional_file_header_offset + IMPORT_TABLE_OFFSET_64];
DWORD* import_table_address = (DWORD*)import_table_data_dir;
DWORD image_section_header_offset = optional_file_header_offset + coff_file_header->SizeOfOptionalHeader;
for (int i = 0; i < coff_file_header->NumberOfSections; i++)
{
IMAGE_SECTION_HEADER* queried_section_header = (IMAGE_SECTION_HEADER*)&bytes[image_section_header_offset];
if (*import_table_address >= queried_section_header->VirtualAddress &&
(*import_table_address < (queried_section_header->VirtualAddress + queried_section_header->SizeOfRawData)))
{
DWORD import_table_offset = *import_table_address - queried_section_header->VirtualAddress + queried_section_header->PointerToRawData;
while(true)
{
IMAGE_IMPORT_DESCRIPTOR* import_table_descriptor = (IMAGE_IMPORT_DESCRIPTOR*)&bytes[import_table_offset];
if (import_table_descriptor->OriginalFirstThunk == 0)
{
break;//Signifies end of IMAGE_IMPORT_DESCRIPTORs
}
// (VA from data directory _entry_ to Image Import Descriptor's element you want) - VA from section header + section header's PointerToRawData
DWORD dependency_name_address = import_table_descriptor->Name;//VA not RVA; ABSOLUTE
DWORD name_offset = dependency_name_address - queried_section_header->VirtualAddress + queried_section_header->PointerToRawData;
char * dependency_name = (char *)&bytes[name_offset];
dependencies.push_back((std::string)dependency_name);
import_table_offset = import_table_offset + sizeof(IMAGE_IMPORT_DESCRIPTOR);
}
}
image_section_header_offset = image_section_header_offset + sizeof(IMAGE_SECTION_HEADER);
}
}
else//32-bit behavior
{
IMAGE_OPTIONAL_HEADER32 * img_opt_header_32 = (IMAGE_OPTIONAL_HEADER32*)&bytes[optional_file_header_offset];
IMAGE_DATA_DIRECTORY* import_table_data_dir = (IMAGE_DATA_DIRECTORY*)&bytes[optional_file_header_offset + IMPORT_TABLE_OFFSET_32];
DWORD* import_table_address = (DWORD*)import_table_data_dir;
DWORD image_section_header_offset = optional_file_header_offset + coff_file_header->SizeOfOptionalHeader;
for (int i = 0; i < coff_file_header->NumberOfSections; i++)
{
IMAGE_SECTION_HEADER* queried_section_header = (IMAGE_SECTION_HEADER*)&bytes[image_section_header_offset];
if (*import_table_address >= queried_section_header->VirtualAddress &&
(*import_table_address < (queried_section_header->VirtualAddress + queried_section_header->SizeOfRawData)))
{
DWORD import_table_offset = *import_table_address - queried_section_header->VirtualAddress + queried_section_header->PointerToRawData;
while (true)
{
IMAGE_IMPORT_DESCRIPTOR* import_table_descriptor = (IMAGE_IMPORT_DESCRIPTOR*)&bytes[import_table_offset];
if (import_table_descriptor->OriginalFirstThunk == 0)
{
break;//Signifies end of IMAGE_IMPORT_DESCRIPTORs
}
// (VA from data directory _entry_ to Image Import Descriptor's element you want) - VA from section header + section header's PointerToRawData
DWORD dependency_name_address = import_table_descriptor->Name;//VA not RVA; ABSOLUTE
DWORD name_offset = dependency_name_address - queried_section_header->VirtualAddress + queried_section_header->PointerToRawData;
char * dependency_name = (char *)&bytes[name_offset];
dependencies.push_back((std::string)dependency_name);
import_table_offset = import_table_offset + sizeof(IMAGE_IMPORT_DESCRIPTOR);
}
}
image_section_header_offset = image_section_header_offset + sizeof(IMAGE_SECTION_HEADER);
}
}
return dependencies;
}
//******************************************************************************
// File Reader
std::vector<char> read_all_bytes(const char* filename)
{
std::ifstream ifs(filename, std::ios::binary | std::ios::ate);
std::ifstream::pos_type pos = ifs.tellg();
std::vector<char> result(pos);
ifs.seekg(0, std::ios::beg);
ifs.read(&result[0], pos);
return result;
}
//******************************************************************************
// IMAGE-TYPE FILE VERIFIER
bool verify_image_file(std::string file_to_verify)
{
if (fs::exists(file_to_verify))
{
size_t extension_query = file_to_verify.find(".dll", 0);
if (extension_query == std::string::npos)
{
extension_query = file_to_verify.find(".DLL", 0);
if (extension_query == std::string::npos)
{
extension_query = file_to_verify.find(".exe", 0);
if (extension_query == std::string::npos)
{
extension_query = file_to_verify.find(".EXE", 0);
}
else { return true; }
if (extension_query != std::string::npos) { return true; }
}
else { return true; }
}
else { return true; }
}
return false;
}
关于c++ - 以编程方式获取用于在非开发人员 Windows 环境中构建进程或库的 DLL 列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43670731/
是否有用于手动测试的代码覆盖工具?比如我新写了30行代码,编译,然后运行,有什么办法可以快速验证这30行都运行了吗? 另外,后来,在我将代码 checkin 正式版本后,有什么方法可以验证测试部门在进
老实说,这是一个家庭作业问题,但我已经浪费了好几个小时,而且无法正确解决。它返回错误数量的结果或错误的数据: 我需要选择参与指导电影和/或在电影中表演的每个人以及他们所做的次数,如果至少 5 次。 有
我正在尝试测试 MacOS 的应用内购买。输入测试用户凭据后,App Store 提示:“当前收据无效或 ds 人员 ID 不匹配。”并且购买失败。 最佳答案 我尝试了很多方法来解决这个问题。 Get
我正在为 Jenkins 使用 ActiveDirectory 插件,因此用户必须使用他们的凭据登录到 Jenkins。然后用户在 Jenkins 中被称为 joe.doe,这很完美。 当同一个人 c
如何从 Infopath 人员/组选取器检索电子邮件地址?当我将人员/组选取器添加到 infopath 表单时,我只得到 3 个字段 DisplayName、AccountId、AccountType
在 Snow Leopard 中,可以在 iCal 事件中显示空闲/忙碌时间。我搜索了 CalStore.framework 的 header ,但找不到任何描述该字段的属性。如何检索日历事件的忙/闲
是否有人成功地从专门针对 SharePoint 2013 的新建或编辑表单中获取用户(个人或组)字段的值? 我已经尝试了通过搜索互联网找到的所有解决方案以及我自己能想到的所有解决方案,所有结果都为空白
所以我需要将一个 Twitter 帐户添加到 ABRecordRef 中。然而,最快的方法似乎是获取社交资料属性的多值引用,创建它的可变版本,查找它是否有 Twitter 条目,如果已经有,则创建
我正在尝试将使用 Tomcat(最初是 5.5,但可以与 7 一起使用)在 MyEclipse 中开发的应用程序部署到我们的演示服务器 (Sun Java Web Server 7)。不幸的是,所有设
我是一名优秀的程序员,十分优秀!