更改.NET中的默認(rèn)時(shí)區(qū)的操作方法
如何更改.NET中的默認(rèn)時(shí)區(qū)?
除了"在操作系統(tǒng)中修改時(shí)區(qū)信息,然后重啟.NET應(yīng)用程序,使其生效"之外。如何在不修改操作系統(tǒng)時(shí)區(qū)的前提下,修改.NET中的默認(rèn)時(shí)區(qū)呢?
這是一位 同學(xué)兼同事 于5月21日在技術(shù)群里問(wèn)的問(wèn)題,我當(dāng)時(shí)簡(jiǎn)單地研究了一下,就寫出來(lái)了。
現(xiàn)在寫文章分享給大家,雖然我覺(jué)得這種需求非常小眾,幾乎不會(huì)有人用到。
正文
正常手段下,.NET是不允許開(kāi)發(fā)者修改默認(rèn)時(shí)區(qū)的,它沒(méi)有公開(kāi)這樣的API。
在 .NET 中,管理時(shí)區(qū)的類型叫 TimeZoneInfo
,它位于 System
命名空間下,由 System.Private.CoreLib.dll
提供。
使用 ILSpy
反編譯 System.Private.CoreLib.dll
,找到 TimeZoneInfo
類型,我們可以看到 TimeZoneInfo.Local
指向一個(gè)私有字段 s_cachedData
的成員屬性 Local
,該字段類型是一個(gè)屬于 TimeZoneInfo
的私有嵌套類型 CachedData
。
當(dāng)首次訪問(wèn) CachedData.Local
時(shí),它會(huì)先檢查 _localTimeZone
私有字段是否有值。如果沒(méi)有值,則調(diào)用 CreateLocal
方法從操作系統(tǒng)獲取時(shí)區(qū)信息并且賦值。
看到了這里,我腦海里就浮現(xiàn)了兩種方案:
- 使用
hook
技術(shù)挾持并修改win32 api
返回的時(shí)區(qū)信息。 - 使用
reflection
技術(shù)反射并且修改時(shí)區(qū)信息。
方案1的優(yōu)點(diǎn)是穩(wěn)定,但可能會(huì)被殺毒軟件報(bào)毒。
方案2的優(yōu)點(diǎn)是不會(huì)報(bào)毒,但可能不穩(wěn)定。
為什么說(shuō)方案2不穩(wěn)定呢?因?yàn)?s_cachedData 私有字段值有可能在某個(gè)時(shí)候被重置。
現(xiàn)在我們來(lái)看看方案2的實(shí)現(xiàn):
public static bool TrySetLocalTimeZoneInfo(TimeZoneInfo timeZoneInfo) { Type timeZoneInfoType = typeof(TimeZoneInfo); // 獲取TimeZoneInfo類型的私有靜態(tài)字段成員信息s_cachedData FieldInfo cachedDataFieldInfo = timeZoneInfoType.GetField("s_cachedData", BindingFlags.NonPublic | BindingFlags.Static); if (cachedDataFieldInfo == null) { return false; } // 獲取TimeZoneInfo類型的私有嵌套類型CachedData Type cachedDataType = timeZoneInfoType.GetNestedType("CachedData", BindingFlags.NonPublic); if (cachedDataType == null) { return false; } // 獲取CachedData類型的私有字段成員信息_localTimeZone FieldInfo localTimeZoneFieldInfo = cachedDataType.GetField("_localTimeZone", BindingFlags.NonPublic | BindingFlags.Instance); if (localTimeZoneFieldInfo == null) { return false; } // 獲取TimeZoneInfo類型的私有靜態(tài)字段s_cachedData值 object cachedData = cachedDataFieldInfo.GetValue(null); if (cachedData == null) { return false; } // 設(shè)置私有字段的值 localTimeZoneFieldInfo.SetValue(cachedData, timeZoneInfo); return true; }
PS: 該方法代碼實(shí)際測(cè)試在 .NET Core 3.1
, .NET 5.0
, .NET 6.0
, .NET 7.0
, .NET 8.0
都可以正常工作。
用法:
void Main() { // 設(shè)置前 Console.WriteLine(TimeZoneInfo.Local); // 修改為 GMT 時(shí)區(qū) TimeZoneInfo hkTimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time"); bool setResult = TrySetLocalTimeZoneInfo(hkTimeZoneInfo); // 設(shè)置后 Console.WriteLine(TimeZoneInfo.Local); }
注意:這種方案需要嚴(yán)謹(jǐn)測(cè)試,反復(fù)驗(yàn)證。
因?yàn)槭谴鄹?NET內(nèi)部私有變量,不知道是否會(huì)引起其它后果。
比如.NET內(nèi)部其它API沒(méi)有使用 TimeZoneInfo.Local
,而是自己在其它地方又緩存了一套 TimeZoneInfo
,那就GG了。
又比如,需要檢查整個(gè) .NET Runtime
和其它第三方組件,是否有調(diào)用 TimeZoneInfo.ClearCachedData
靜態(tài)方法 或者 調(diào)用 CultureInfo.ClearCachedData
對(duì)象方法。
到此這篇關(guān)于如何更改.NET中的默認(rèn)時(shí)區(qū)?的文章就介紹到這了,更多相關(guān).NET默認(rèn)時(shí)區(qū)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
比較簡(jiǎn)單的將數(shù)據(jù)信息導(dǎo)入wrod文檔方案(C# for word)
史上最簡(jiǎn)單將數(shù)據(jù)信息導(dǎo)入wrod文檔方案(C# for word)2010-01-01vs2010制作簡(jiǎn)單的asp.net網(wǎng)站
這篇文章主要介紹了vs2010制作簡(jiǎn)單的asp.net網(wǎng)站,只要十步哦,感興趣的小伙伴們可以參考一下2015-09-09.net core下對(duì)于附件上傳下載的實(shí)現(xiàn)示例
本篇文章主要介紹了.net core下對(duì)于附件上傳下載的實(shí)現(xiàn)示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-03-03.Net Core讀取Json配置文件的實(shí)現(xiàn)示例
這篇文章主要介紹了.Net Core讀取Json配置文件的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-11-11ASP.NET Cookie 操作實(shí)現(xiàn)
本節(jié)中的主題描述如何在 ASP.NET Web 應(yīng)用程序中創(chuàng)建 Cookie。Cookie 是一些小的文本文件,服務(wù)器和瀏覽器在收到每個(gè)頁(yè)請(qǐng)求時(shí)交換它們,您還可以使用這些小文本文件來(lái)存儲(chǔ)幫助針對(duì)每個(gè)用戶自定義您的應(yīng)用程序的信息。2009-11-11linq 查詢 Linq 高級(jí)查詢實(shí)例代碼
本文針對(duì)Linq 高級(jí)查詢實(shí)例進(jìn)行詳解,需要了解的朋友可以參考下2013-01-01DataSet、DataTable、DataRow區(qū)別詳解
這篇文章主要介紹了DataSet、DataTable、DataRow區(qū)別詳解,需要的朋友可以參考下2014-02-02